| 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 |