OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 /* | 5 /* |
6 * Code for dealing with X509.V3 extensions. | 6 * Code for dealing with X509.V3 extensions. |
7 */ | 7 */ |
8 | 8 |
9 #include "cert.h" | 9 #include "cert.h" |
10 #include "secitem.h" | 10 #include "secitem.h" |
11 #include "secoid.h" | 11 #include "secoid.h" |
12 #include "secder.h" | 12 #include "secder.h" |
13 #include "secasn1.h" | 13 #include "secasn1.h" |
14 #include "certxutl.h" | 14 #include "certxutl.h" |
15 #include "secerr.h" | 15 #include "secerr.h" |
16 | 16 |
17 SECStatus | 17 SECStatus |
18 CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid, | 18 CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid, SECItem *value) |
19 » » » SECItem *value) | |
20 { | 19 { |
21 return (cert_FindExtensionByOID (cert->extensions, oid, value)); | 20 return (cert_FindExtensionByOID(cert->extensions, oid, value)); |
22 } | 21 } |
23 | |
24 | 22 |
25 SECStatus | 23 SECStatus |
26 CERT_FindCertExtension(const CERTCertificate *cert, int tag, SECItem *value) | 24 CERT_FindCertExtension(const CERTCertificate *cert, int tag, SECItem *value) |
27 { | 25 { |
28 return (cert_FindExtension (cert->extensions, tag, value)); | 26 return (cert_FindExtension(cert->extensions, tag, value)); |
29 } | 27 } |
30 | 28 |
31 static void | 29 static void |
32 SetExts(void *object, CERTCertExtension **exts) | 30 SetExts(void *object, CERTCertExtension **exts) |
33 { | 31 { |
34 CERTCertificate *cert = (CERTCertificate *)object; | 32 CERTCertificate *cert = (CERTCertificate *)object; |
35 | 33 |
36 cert->extensions = exts; | 34 cert->extensions = exts; |
37 DER_SetUInteger (cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3); | 35 DER_SetUInteger(cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3); |
38 } | 36 } |
39 | 37 |
40 void * | 38 void * |
41 CERT_StartCertExtensions(CERTCertificate *cert) | 39 CERT_StartCertExtensions(CERTCertificate *cert) |
42 { | 40 { |
43 return (cert_StartExtensions ((void *)cert, cert->arena, SetExts)); | 41 return (cert_StartExtensions((void *)cert, cert->arena, SetExts)); |
44 } | 42 } |
45 | 43 |
46 /* | 44 /* |
47 * get the value of the Netscape Certificate Type Extension | 45 * get the value of the Netscape Certificate Type Extension |
48 */ | 46 */ |
49 SECStatus | 47 SECStatus |
50 CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem) | 48 CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem) |
51 { | 49 { |
52 | 50 |
53 return (CERT_FindBitStringExtension | 51 return (CERT_FindBitStringExtension( |
54 » (cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem)); | 52 cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem)); |
55 } | 53 } |
56 | 54 |
57 | |
58 /* | 55 /* |
59 * get the value of a string type extension | 56 * get the value of a string type extension |
60 */ | 57 */ |
61 char * | 58 char * |
62 CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag) | 59 CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag) |
63 { | 60 { |
64 SECItem wrapperItem, tmpItem = {siBuffer,0}; | 61 SECItem wrapperItem, tmpItem = { siBuffer, 0 }; |
65 SECStatus rv; | 62 SECStatus rv; |
66 PLArenaPool *arena = NULL; | 63 PLArenaPool *arena = NULL; |
67 char *retstring = NULL; | 64 char *retstring = NULL; |
68 | 65 |
69 wrapperItem.data = NULL; | 66 wrapperItem.data = NULL; |
70 tmpItem.data = NULL; | 67 tmpItem.data = NULL; |
71 | 68 |
72 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 69 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
73 | 70 |
74 if ( ! arena ) { | 71 if (!arena) { |
75 » goto loser; | 72 goto loser; |
76 } | |
77 | |
78 rv = cert_FindExtension(cert->extensions, oidtag, | |
79 » » » &wrapperItem); | |
80 if ( rv != SECSuccess ) { | |
81 » goto loser; | |
82 } | 73 } |
83 | 74 |
84 rv = SEC_QuickDERDecodeItem(arena, &tmpItem, | 75 rv = cert_FindExtension(cert->extensions, oidtag, &wrapperItem); |
85 SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem); | 76 if (rv != SECSuccess) { |
86 | 77 goto loser; |
87 if ( rv != SECSuccess ) { | |
88 » goto loser; | |
89 } | 78 } |
90 | 79 |
91 retstring = (char *)PORT_Alloc(tmpItem.len + 1 ); | 80 rv = SEC_QuickDERDecodeItem( |
92 if ( retstring == NULL ) { | 81 arena, &tmpItem, SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem); |
93 » goto loser; | 82 |
| 83 if (rv != SECSuccess) { |
| 84 goto loser; |
94 } | 85 } |
95 | 86 |
| 87 retstring = (char *)PORT_Alloc(tmpItem.len + 1); |
| 88 if (retstring == NULL) { |
| 89 goto loser; |
| 90 } |
| 91 |
96 PORT_Memcpy(retstring, tmpItem.data, tmpItem.len); | 92 PORT_Memcpy(retstring, tmpItem.data, tmpItem.len); |
97 retstring[tmpItem.len] = '\0'; | 93 retstring[tmpItem.len] = '\0'; |
98 | 94 |
99 loser: | 95 loser: |
100 if ( arena ) { | 96 if (arena) { |
101 » PORT_FreeArena(arena, PR_FALSE); | 97 PORT_FreeArena(arena, PR_FALSE); |
102 } | |
103 | |
104 if ( wrapperItem.data ) { | |
105 » PORT_Free(wrapperItem.data); | |
106 } | 98 } |
107 | 99 |
108 return(retstring); | 100 if (wrapperItem.data) { |
| 101 PORT_Free(wrapperItem.data); |
| 102 } |
| 103 |
| 104 return (retstring); |
109 } | 105 } |
110 | 106 |
111 /* | 107 /* |
112 * get the value of the X.509 v3 Key Usage Extension | 108 * get the value of the X.509 v3 Key Usage Extension |
113 */ | 109 */ |
114 SECStatus | 110 SECStatus |
115 CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem) | 111 CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem) |
116 { | 112 { |
117 | 113 |
118 return (CERT_FindBitStringExtension(cert->extensions, | 114 return (CERT_FindBitStringExtension(cert->extensions, |
119 » » » » » SEC_OID_X509_KEY_USAGE, retItem)); | 115 SEC_OID_X509_KEY_USAGE, retItem)); |
120 } | 116 } |
121 | 117 |
122 /* | 118 /* |
123 * get the value of the X.509 v3 Key Usage Extension | 119 * get the value of the X.509 v3 Key Usage Extension |
124 */ | 120 */ |
125 SECStatus | 121 SECStatus |
126 CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem) | 122 CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem) |
127 { | 123 { |
128 | 124 |
129 SECStatus rv; | 125 SECStatus rv; |
130 SECItem encodedValue = {siBuffer, NULL, 0 }; | 126 SECItem encodedValue = { siBuffer, NULL, 0 }; |
131 SECItem decodedValue = {siBuffer, NULL, 0 }; | 127 SECItem decodedValue = { siBuffer, NULL, 0 }; |
132 | 128 |
133 rv = cert_FindExtension | 129 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, |
134 » (cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID, &encodedValue); | 130 &encodedValue); |
135 if (rv == SECSuccess) { | 131 if (rv == SECSuccess) { |
136 » PLArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 132 PLArenaPool *tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
137 » if (tmpArena) { | 133 if (tmpArena) { |
138 » rv = SEC_QuickDERDecodeItem(tmpArena, &decodedValue, | 134 rv = SEC_QuickDERDecodeItem(tmpArena, &decodedValue, |
139 » SEC_ASN1_GET(SEC_OctetStringTemplate), | 135 SEC_ASN1_GET(SEC_OctetStringTemplate), |
140 » » » » » &encodedValue); | 136 &encodedValue); |
141 » if (rv == SECSuccess) { | 137 if (rv == SECSuccess) { |
142 » rv = SECITEM_CopyItem(NULL, retItem, &decodedValue); | 138 rv = SECITEM_CopyItem(NULL, retItem, &decodedValue); |
143 » } | 139 } |
144 » PORT_FreeArena(tmpArena, PR_FALSE); | 140 PORT_FreeArena(tmpArena, PR_FALSE); |
145 » } else { | 141 } else { |
146 » rv = SECFailure; | 142 rv = SECFailure; |
147 » } | 143 } |
148 } | 144 } |
149 SECITEM_FreeItem(&encodedValue, PR_FALSE); | 145 SECITEM_FreeItem(&encodedValue, PR_FALSE); |
150 return rv; | 146 return rv; |
151 } | 147 } |
152 | 148 |
153 SECStatus | 149 SECStatus |
154 CERT_FindBasicConstraintExten(CERTCertificate *cert, | 150 CERT_FindBasicConstraintExten(CERTCertificate *cert, |
155 » » » CERTBasicConstraints *value) | 151 CERTBasicConstraints *value) |
156 { | 152 { |
157 SECItem encodedExtenValue; | 153 SECItem encodedExtenValue; |
158 SECStatus rv; | 154 SECStatus rv; |
159 | 155 |
160 encodedExtenValue.data = NULL; | 156 encodedExtenValue.data = NULL; |
161 encodedExtenValue.len = 0; | 157 encodedExtenValue.len = 0; |
162 | 158 |
163 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS, | 159 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS, |
164 » » » &encodedExtenValue); | 160 &encodedExtenValue); |
165 if ( rv != SECSuccess ) { | 161 if (rv != SECSuccess) { |
166 » return (rv); | 162 return (rv); |
167 } | 163 } |
168 | 164 |
169 rv = CERT_DecodeBasicConstraintValue (value, &encodedExtenValue); | 165 rv = CERT_DecodeBasicConstraintValue(value, &encodedExtenValue); |
170 | 166 |
171 /* free the raw extension data */ | 167 /* free the raw extension data */ |
172 PORT_Free(encodedExtenValue.data); | 168 PORT_Free(encodedExtenValue.data); |
173 encodedExtenValue.data = NULL; | 169 encodedExtenValue.data = NULL; |
174 | 170 |
175 return(rv); | 171 return (rv); |
176 } | 172 } |
177 | 173 |
178 CERTAuthKeyID * | 174 CERTAuthKeyID * |
179 CERT_FindAuthKeyIDExten (PLArenaPool *arena, CERTCertificate *cert) | 175 CERT_FindAuthKeyIDExten(PLArenaPool *arena, CERTCertificate *cert) |
180 { | 176 { |
181 SECItem encodedExtenValue; | 177 SECItem encodedExtenValue; |
182 SECStatus rv; | 178 SECStatus rv; |
183 CERTAuthKeyID *ret; | 179 CERTAuthKeyID *ret; |
184 | 180 |
185 encodedExtenValue.data = NULL; | 181 encodedExtenValue.data = NULL; |
186 encodedExtenValue.len = 0; | 182 encodedExtenValue.len = 0; |
187 | 183 |
188 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID, | 184 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID, |
189 » » » &encodedExtenValue); | 185 &encodedExtenValue); |
190 if ( rv != SECSuccess ) { | 186 if (rv != SECSuccess) { |
191 » return (NULL); | 187 return (NULL); |
192 } | 188 } |
193 | 189 |
194 ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue); | 190 ret = CERT_DecodeAuthKeyID(arena, &encodedExtenValue); |
195 | 191 |
196 PORT_Free(encodedExtenValue.data); | 192 PORT_Free(encodedExtenValue.data); |
197 encodedExtenValue.data = NULL; | 193 encodedExtenValue.data = NULL; |
198 | 194 |
199 return(ret); | 195 return (ret); |
200 } | 196 } |
201 | 197 |
202 SECStatus | 198 SECStatus |
203 CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage) | 199 CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage) |
204 { | 200 { |
205 SECItem keyUsage; | 201 SECItem keyUsage; |
206 SECStatus rv; | 202 SECStatus rv; |
207 | 203 |
208 /* There is no extension, v1 or v2 certificate */ | 204 /* There is no extension, v1 or v2 certificate */ |
209 if (cert->extensions == NULL) { | 205 if (cert->extensions == NULL) { |
210 » return (SECSuccess); | 206 return (SECSuccess); |
211 } | 207 } |
212 | 208 |
213 keyUsage.data = NULL; | 209 keyUsage.data = NULL; |
214 | 210 |
215 /* This code formerly ignored the Key Usage extension if it was | 211 /* This code formerly ignored the Key Usage extension if it was |
216 ** marked non-critical. That was wrong. Since we do understand it, | 212 ** marked non-critical. That was wrong. Since we do understand it, |
217 ** we are obligated to honor it, whether or not it is critical. | 213 ** we are obligated to honor it, whether or not it is critical. |
218 */ | 214 */ |
219 rv = CERT_FindKeyUsageExtension(cert, &keyUsage); | 215 rv = CERT_FindKeyUsageExtension(cert, &keyUsage); |
220 if (rv == SECFailure) { | 216 if (rv == SECFailure) { |
221 rv = (PORT_GetError () == SEC_ERROR_EXTENSION_NOT_FOUND) ? | 217 rv = (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) ? SECSuccess |
222 » SECSuccess : SECFailure; | 218 : SECFailure; |
223 } else if (!(keyUsage.data[0] & usage)) { | 219 } else if (!(keyUsage.data[0] & usage)) { |
224 » PORT_SetError (SEC_ERROR_CERT_USAGES_INVALID); | 220 PORT_SetError(SEC_ERROR_CERT_USAGES_INVALID); |
225 » rv = SECFailure; | 221 rv = SECFailure; |
226 } | 222 } |
227 PORT_Free (keyUsage.data); | 223 PORT_Free(keyUsage.data); |
228 return (rv); | 224 return (rv); |
229 } | 225 } |
OLD | NEW |