/src/nss/lib/pkcs12/p12plcy.c
Line | Count | Source |
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 | 20.2k | { |
40 | 20.2k | PRUint32 policy; |
41 | 20.2k | SECStatus rv; |
42 | | |
43 | 20.2k | rv = NSS_GetAlgorithmPolicy(alg, &policy); |
44 | 20.2k | if (rv != SECSuccess) { |
45 | 0 | return PR_FALSE; |
46 | 0 | } |
47 | 20.2k | if ((policy & needed) == needed) { |
48 | 20.2k | return PR_TRUE; |
49 | 20.2k | } |
50 | 4 | return PR_FALSE; |
51 | 20.2k | } |
52 | | |
53 | | PRBool |
54 | | SEC_PKCS12CipherAllowed(SECOidTag pbeAlg, SECOidTag hmacAlg) |
55 | 0 | { |
56 | 0 | SECOidTag cipherAlg = SEC_PKCS5GetCryptoFromAlgTag(pbeAlg); |
57 | 0 | SECOidTag hashAlg = SEC_PKCS5GetHashFromAlgTag(pbeAlg); |
58 | 0 | 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 | 0 | cipherAlg = pbeAlg; |
64 | 0 | hashAlg = HASH_GetHashOidTagByHMACOidTag(hmacAlg); |
65 | 0 | } |
66 | 0 | if ((cipherAlg == SEC_OID_UNKNOWN) || (hashAlg == SEC_OID_UNKNOWN)) { |
67 | 0 | return PR_FALSE; |
68 | 0 | } |
69 | 0 | if (!sec_PKCS12Allowed(cipherAlg, NSS_USE_ALG_IN_PKCS12)) { |
70 | 0 | return PR_FALSE; |
71 | 0 | } |
72 | 0 | return sec_PKCS12Allowed(hashAlg, NSS_USE_ALG_IN_PKCS12); |
73 | 0 | } |
74 | | |
75 | | PRBool |
76 | | SEC_PKCS12DecryptionAllowed(SECAlgorithmID *algid) |
77 | 10.1k | { |
78 | 10.1k | SECOidTag algtag; |
79 | | |
80 | 10.1k | algtag = SEC_PKCS5GetCryptoAlgorithm(algid); |
81 | 10.1k | if (algtag == SEC_OID_UNKNOWN) { |
82 | 89 | return PR_FALSE; |
83 | 89 | } |
84 | | |
85 | 10.0k | if (!sec_PKCS12Allowed(algtag, NSS_USE_ALG_IN_PKCS12_DECRYPT)) { |
86 | 3 | return PR_FALSE; |
87 | 3 | } |
88 | | |
89 | 10.0k | algtag = SEC_PKCS5GetHashAlgorithm(algid); |
90 | 10.0k | if (algtag == SEC_OID_UNKNOWN) { |
91 | 5 | return PR_FALSE; |
92 | 5 | } |
93 | 10.0k | return sec_PKCS12Allowed(algtag, NSS_USE_ALG_IN_PKCS12_DECRYPT); |
94 | 10.0k | } |
95 | | |
96 | | PRBool |
97 | | SEC_PKCS12IntegrityHashAllowed(SECOidTag hashAlg, PRBool verify) |
98 | 205 | { |
99 | 205 | return sec_PKCS12Allowed(hashAlg, verify ? NSS_USE_ALG_IN_PKCS12_DECRYPT : NSS_USE_ALG_IN_PKCS12); |
100 | 205 | } |
101 | | |
102 | | /* is any encryption allowed? */ |
103 | | PRBool |
104 | | SEC_PKCS12IsEncryptionAllowed(void) |
105 | 0 | { |
106 | 0 | int i; |
107 | |
|
108 | 0 | 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 | 0 | if (sec_PKCS12Allowed(pkcs12SuiteMaps[i].algTag, NSS_USE_ALG_IN_PKCS12)) { |
112 | 0 | return PR_TRUE; |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | 0 | return PR_FALSE; |
117 | 0 | } |
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 | 0 | { |
125 | 0 | int i; |
126 | 0 | PRUint32 set = on ? NSS_USE_ALG_IN_PKCS12 : 0; |
127 | 0 | PRUint32 clear = on ? 0 : NSS_USE_ALG_IN_PKCS12; |
128 | |
|
129 | 0 | for (i = 0; pkcs12SuiteMaps[i].suite != 0L; i++) { |
130 | 0 | if (pkcs12SuiteMaps[i].suite == (unsigned long)which) { |
131 | 0 | return NSS_SetAlgorithmPolicy(pkcs12SuiteMaps[i].algTag, set, clear); |
132 | 0 | } |
133 | 0 | } |
134 | 0 | PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
135 | 0 | return SECFailure; |
136 | 0 | } |
137 | | |
138 | | SECStatus |
139 | | SEC_PKCS12SetPreferredCipher(long which, int on) |
140 | 0 | { |
141 | | /* nothing looked at the preferences in the suite maps, so this function |
142 | | * has always been a noop */ |
143 | 0 | return SECSuccess; |
144 | 0 | } |