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