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 #include "cert.h" | 5 #include "cert.h" |
6 #include "secpkcs7.h" | 6 #include "secpkcs7.h" |
7 #include "base64.h" | 7 #include "base64.h" |
8 #include "secitem.h" | 8 #include "secitem.h" |
9 #include "secder.h" | 9 #include "secder.h" |
10 #include "secasn1.h" | 10 #include "secasn1.h" |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 | 138 |
139 PORT_Free(der.data); | 139 PORT_Free(der.data); |
140 return cert; | 140 return cert; |
141 } | 141 } |
142 | 142 |
143 static const char NS_CERT_HEADER[] = "-----BEGIN CERTIFICATE-----"; | 143 static const char NS_CERT_HEADER[] = "-----BEGIN CERTIFICATE-----"; |
144 static const char NS_CERT_TRAILER[] = "-----END CERTIFICATE-----"; | 144 static const char NS_CERT_TRAILER[] = "-----END CERTIFICATE-----"; |
145 #define NS_CERT_HEADER_LEN ((sizeof NS_CERT_HEADER) - 1) | 145 #define NS_CERT_HEADER_LEN ((sizeof NS_CERT_HEADER) - 1) |
146 #define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1) | 146 #define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1) |
147 | 147 |
148 static const char CERTIFICATE_TYPE_STRING[] = "certificate"; | |
149 #define CERTIFICATE_TYPE_LEN (sizeof(CERTIFICATE_TYPE_STRING)-1) | |
150 | |
151 /* | 148 /* |
152 * read an old style ascii or binary certificate chain | 149 * read an old style ascii or binary certificate chain |
153 */ | 150 */ |
154 SECStatus | 151 SECStatus |
155 CERT_DecodeCertPackage(char *certbuf, | 152 CERT_DecodeCertPackage(char *certbuf, |
156 int certlen, | 153 int certlen, |
157 CERTImportCertificateFunc f, | 154 CERTImportCertificateFunc f, |
158 void *arg) | 155 void *arg) |
159 { | 156 { |
160 unsigned char *cp; | 157 unsigned char *cp; |
161 unsigned char *bincert = NULL; | 158 unsigned char *bincert = NULL; |
162 char * ascCert = NULL; | 159 char * ascCert = NULL; |
163 SECStatus rv; | 160 SECStatus rv; |
164 | 161 |
165 if ( certbuf == NULL ) { | 162 if ( certbuf == NULL ) { |
| 163 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| 164 return(SECFailure); |
| 165 } |
| 166 /* |
| 167 * Make sure certlen is long enough to handle the longest possible |
| 168 * reference in the code below: |
| 169 * 0x30 0x84 l1 l2 l3 l4 + |
| 170 * tag 9 o1 o2 o3 o4 o5 o6 o7 o8 o9 |
| 171 * 6 + 11 = 17. 17 bytes is clearly too small to code any kind of |
| 172 * certificate (a 128 bit ECC certificate contains at least an 8 byte |
| 173 * key and a 16 byte signature, plus coding overhead). Typically a cert |
| 174 * is much larger. So it's safe to require certlen to be at least 17 |
| 175 * bytes. |
| 176 */ |
| 177 if (certlen < 17) { |
| 178 PORT_SetError(SEC_ERROR_INPUT_LEN); |
166 return(SECFailure); | 179 return(SECFailure); |
167 } | 180 } |
168 | 181 |
169 cp = (unsigned char *)certbuf; | 182 cp = (unsigned char *)certbuf; |
170 | 183 |
171 /* is a DER encoded certificate of some type? */ | 184 /* is a DER encoded certificate of some type? */ |
172 if ( ( *cp & 0x1f ) == SEC_ASN1_SEQUENCE ) { | 185 if ( ( *cp & 0x1f ) == SEC_ASN1_SEQUENCE ) { |
173 SECItem certitem; | 186 SECItem certitem; |
174 SECItem *pcertitem = &certitem; | 187 SECItem *pcertitem = &certitem; |
175 int seqLen, seqLenLen; | 188 int seqLen, seqLenLen; |
(...skipping 11 matching lines...) Expand all Loading... |
187 break; | 200 break; |
188 case 3: | 201 case 3: |
189 seqLen = ((unsigned long)cp[1]<<16) | (cp[2]<<8) | cp[3]; | 202 seqLen = ((unsigned long)cp[1]<<16) | (cp[2]<<8) | cp[3]; |
190 break; | 203 break; |
191 case 2: | 204 case 2: |
192 seqLen = (cp[1]<<8) | cp[2]; | 205 seqLen = (cp[1]<<8) | cp[2]; |
193 break; | 206 break; |
194 case 1: | 207 case 1: |
195 seqLen = cp[1]; | 208 seqLen = cp[1]; |
196 break; | 209 break; |
197 » default: | 210 » case 0: |
198 /* indefinite length */ | 211 /* indefinite length */ |
199 seqLen = 0; | 212 seqLen = 0; |
| 213 break; |
| 214 default: |
| 215 goto notder; |
200 } | 216 } |
201 cp += ( seqLenLen + 1 ); | 217 cp += ( seqLenLen + 1 ); |
202 | 218 |
203 } else { | 219 } else { |
204 seqLenLen = 0; | 220 seqLenLen = 0; |
205 seqLen = *cp; | 221 seqLen = *cp; |
206 cp++; | 222 cp++; |
207 } | 223 } |
208 | 224 |
209 /* check entire length if definite length */ | 225 /* check entire length if definite length */ |
210 if ( seqLen || seqLenLen ) { | 226 if ( seqLen || seqLenLen ) { |
211 if ( certlen != ( seqLen + seqLenLen + 2 ) ) { | 227 if ( certlen != ( seqLen + seqLenLen + 2 ) ) { |
212 if (certlen > ( seqLen + seqLenLen + 2 )) | 228 if (certlen > ( seqLen + seqLenLen + 2 )) |
213 PORT_SetError(SEC_ERROR_EXTRA_INPUT); | 229 PORT_SetError(SEC_ERROR_EXTRA_INPUT); |
214 else | 230 else |
215 PORT_SetError(SEC_ERROR_INPUT_LEN); | 231 PORT_SetError(SEC_ERROR_INPUT_LEN); |
216 goto notder; | 232 goto notder; |
217 } | 233 } |
218 } | 234 } |
219 | 235 |
220 » /* check the type string */ | 236 » /* check the type oid */ |
221 » /* netscape wrapped DER cert */ | 237 » if ( cp[0] == SEC_ASN1_OBJECT_ID ) { |
222 » if ( ( cp[0] == SEC_ASN1_OCTET_STRING ) && | |
223 » ( cp[1] == CERTIFICATE_TYPE_LEN ) && | |
224 » ( PORT_Strcmp((char *)&cp[2], CERTIFICATE_TYPE_STRING) ) ) { | |
225 » | |
226 » cp += ( CERTIFICATE_TYPE_LEN + 2 ); | |
227 | |
228 » /* it had better be a certificate by now!! */ | |
229 » certitem.data = cp; | |
230 » certitem.len = certlen - ( cp - (unsigned char *)certbuf ); | |
231 » | |
232 » rv = (* f)(arg, &pcertitem, 1); | |
233 » | |
234 » return(rv); | |
235 » } else if ( cp[0] == SEC_ASN1_OBJECT_ID ) { | |
236 SECOidData *oiddata; | 238 SECOidData *oiddata; |
237 SECItem oiditem; | 239 SECItem oiditem; |
238 /* XXX - assume DER encoding of OID len!! */ | 240 /* XXX - assume DER encoding of OID len!! */ |
239 oiditem.len = cp[1]; | 241 oiditem.len = cp[1]; |
| 242 /* if we add an oid below that is longer than 9 bytes, then we |
| 243 * need to change the certlen check at the top of the function |
| 244 * to prevent a buffer overflow |
| 245 */ |
| 246 if ( oiditem.len > 9 ) { |
| 247 PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID); |
| 248 return(SECFailure); |
| 249 } |
240 oiditem.data = (unsigned char *)&cp[2]; | 250 oiditem.data = (unsigned char *)&cp[2]; |
241 oiddata = SECOID_FindOID(&oiditem); | 251 oiddata = SECOID_FindOID(&oiditem); |
242 if ( oiddata == NULL ) { | 252 if ( oiddata == NULL ) { |
243 return(SECFailure); | 253 return(SECFailure); |
244 } | 254 } |
245 | 255 |
246 certitem.data = (unsigned char*)certbuf; | 256 certitem.data = (unsigned char*)certbuf; |
247 certitem.len = certlen; | 257 certitem.len = certlen; |
248 | 258 |
249 switch ( oiddata->offset ) { | 259 switch ( oiddata->offset ) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 if ( rv == SECSuccess ) { | 425 if ( rv == SECSuccess ) { |
416 cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), | 426 cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), |
417 &collectArgs.cert, NULL, | 427 &collectArgs.cert, NULL, |
418 PR_FALSE, PR_TRUE); | 428 PR_FALSE, PR_TRUE); |
419 } | 429 } |
420 | 430 |
421 PORT_FreeArena(collectArgs.arena, PR_FALSE); | 431 PORT_FreeArena(collectArgs.arena, PR_FALSE); |
422 | 432 |
423 return(cert); | 433 return(cert); |
424 } | 434 } |
OLD | NEW |