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