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