p12plcy.c (4465B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "p12plcy.h" 6 #include "secoid.h" 7 #include "secport.h" 8 #include "secpkcs5.h" 9 #include "secerr.h" 10 #include "sechash.h" 11 12 #define PKCS12_NULL 0x0000 13 14 typedef struct pkcs12SuiteMapStr { 15 SECOidTag algTag; 16 unsigned int keyLengthBits; /* in bits */ 17 unsigned long suite; 18 PRBool allowed; 19 PRBool preferred; 20 } pkcs12SuiteMap; 21 22 static pkcs12SuiteMap pkcs12SuiteMaps[] = { 23 { SEC_OID_RC4, 40, PKCS12_RC4_40, PR_FALSE, PR_FALSE }, 24 { SEC_OID_RC4, 128, PKCS12_RC4_128, PR_FALSE, PR_FALSE }, 25 { SEC_OID_RC2_CBC, 40, PKCS12_RC2_CBC_40, PR_FALSE, PR_TRUE }, 26 { SEC_OID_RC2_CBC, 128, PKCS12_RC2_CBC_128, PR_FALSE, PR_FALSE }, 27 { SEC_OID_DES_CBC, 64, PKCS12_DES_56, PR_FALSE, PR_FALSE }, 28 { SEC_OID_DES_EDE3_CBC, 192, PKCS12_DES_EDE3_168, PR_FALSE, PR_FALSE }, 29 { SEC_OID_AES_128_CBC, 128, PKCS12_AES_CBC_128, PR_FALSE, PR_FALSE }, 30 { SEC_OID_AES_192_CBC, 192, PKCS12_AES_CBC_192, PR_FALSE, PR_FALSE }, 31 { SEC_OID_AES_256_CBC, 256, PKCS12_AES_CBC_256, PR_FALSE, PR_FALSE }, 32 { SEC_OID_UNKNOWN, 0, PKCS12_NULL, PR_FALSE, PR_FALSE }, 33 { SEC_OID_UNKNOWN, 0, 0L, PR_FALSE, PR_FALSE } 34 }; 35 36 /* determine if algid is an algorithm which is allowed */ 37 static PRBool 38 sec_PKCS12Allowed(SECOidTag alg, PRUint32 needed) 39 { 40 PRUint32 policy; 41 SECStatus rv; 42 43 rv = NSS_GetAlgorithmPolicy(alg, &policy); 44 if (rv != SECSuccess) { 45 return PR_FALSE; 46 } 47 if ((policy & needed) == needed) { 48 return PR_TRUE; 49 } 50 return PR_FALSE; 51 } 52 53 PRBool 54 SEC_PKCS12CipherAllowed(SECOidTag pbeAlg, SECOidTag hmacAlg) 55 { 56 SECOidTag cipherAlg = SEC_PKCS5GetCryptoFromAlgTag(pbeAlg); 57 SECOidTag hashAlg = SEC_PKCS5GetHashFromAlgTag(pbeAlg); 58 if (cipherAlg == SEC_OID_UNKNOWN) { 59 /* not a traditional PBE (PKCS5v1 or PKCS12) 60 * Our PKCS #12 code accepts ciphers algs here 61 * which get turned into PKCS 5v2 algids. In 62 * this case we already have the cipher alg */ 63 cipherAlg = pbeAlg; 64 hashAlg = HASH_GetHashOidTagByHMACOidTag(hmacAlg); 65 } 66 if ((cipherAlg == SEC_OID_UNKNOWN) || (hashAlg == SEC_OID_UNKNOWN)) { 67 return PR_FALSE; 68 } 69 if (!sec_PKCS12Allowed(cipherAlg, NSS_USE_ALG_IN_PKCS12)) { 70 return PR_FALSE; 71 } 72 return sec_PKCS12Allowed(hashAlg, NSS_USE_ALG_IN_PKCS12); 73 } 74 75 PRBool 76 SEC_PKCS12DecryptionAllowed(SECAlgorithmID *algid) 77 { 78 SECOidTag algtag; 79 80 algtag = SEC_PKCS5GetCryptoAlgorithm(algid); 81 if (algtag == SEC_OID_UNKNOWN) { 82 return PR_FALSE; 83 } 84 85 if (!sec_PKCS12Allowed(algtag, NSS_USE_ALG_IN_PKCS12_DECRYPT)) { 86 return PR_FALSE; 87 } 88 89 algtag = SEC_PKCS5GetHashAlgorithm(algid); 90 if (algtag == SEC_OID_UNKNOWN) { 91 return PR_FALSE; 92 } 93 return sec_PKCS12Allowed(algtag, NSS_USE_ALG_IN_PKCS12_DECRYPT); 94 } 95 96 PRBool 97 SEC_PKCS12IntegrityHashAllowed(SECOidTag hashAlg, PRBool verify) 98 { 99 return sec_PKCS12Allowed(hashAlg, verify ? NSS_USE_ALG_IN_PKCS12_DECRYPT : NSS_USE_ALG_IN_PKCS12); 100 } 101 102 /* is any encryption allowed? */ 103 PRBool 104 SEC_PKCS12IsEncryptionAllowed(void) 105 { 106 int i; 107 108 for (i = 0; pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN; i++) { 109 /* we're going to return true here if any of the traditional 110 * algorithms are enabled */ 111 if (sec_PKCS12Allowed(pkcs12SuiteMaps[i].algTag, NSS_USE_ALG_IN_PKCS12)) { 112 return PR_TRUE; 113 } 114 } 115 116 return PR_FALSE; 117 } 118 119 /* keep the traditional enable/disable for old ciphers so old applications 120 * continue to work. This only works for the traditional pkcs12 values, 121 * you need to use NSS_SetAlgorithmPolicy directly for other ciphers. */ 122 SECStatus 123 SEC_PKCS12EnableCipher(long which, int on) 124 { 125 int i; 126 PRUint32 set = on ? NSS_USE_ALG_IN_PKCS12 : 0; 127 PRUint32 clear = on ? 0 : NSS_USE_ALG_IN_PKCS12; 128 129 for (i = 0; pkcs12SuiteMaps[i].suite != 0L; i++) { 130 if (pkcs12SuiteMaps[i].suite == (unsigned long)which) { 131 return NSS_SetAlgorithmPolicy(pkcs12SuiteMaps[i].algTag, set, clear); 132 } 133 } 134 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 135 return SECFailure; 136 } 137 138 SECStatus 139 SEC_PKCS12SetPreferredCipher(long which, int on) 140 { 141 /* nothing looked at the preferences in the suite maps, so this function 142 * has always been a noop */ 143 return SECSuccess; 144 }