📄 x509v3.c
字号:
if (hdr.tag != 3) { wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " "Context-Specific tag %d in optional " "tbsCertificate fields", hdr.tag); return 0; } /* extensions [3] EXPLICIT Extensions OPTIONAL */ if (cert->version != X509_CERT_V3) { wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " "Extensions data which are only allowed for " "version 3", cert->version + 1); return -1; } if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) return -1; pos = hdr.payload + hdr.length; if (pos < end) { wpa_hexdump(MSG_DEBUG, "X509: Ignored extra tbsCertificate data", pos, end - pos); } return 0;}static int x509_rsadsi_oid(struct asn1_oid *oid){ return oid->len >= 4 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 2 /* member-body */ && oid->oid[2] == 840 /* us */ && oid->oid[3] == 113549 /* rsadsi */;}static int x509_pkcs_oid(struct asn1_oid *oid){ return oid->len >= 5 && x509_rsadsi_oid(oid) && oid->oid[4] == 1 /* pkcs */;}static int x509_digest_oid(struct asn1_oid *oid){ return oid->len >= 5 && x509_rsadsi_oid(oid) && oid->oid[4] == 2 /* digestAlgorithm */;}static int x509_sha1_oid(struct asn1_oid *oid){ return oid->len == 6 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 3 /* identified-organization */ && oid->oid[2] == 14 /* oiw */ && oid->oid[3] == 3 /* secsig */ && oid->oid[4] == 2 /* algorithms */ && oid->oid[5] == 26 /* id-sha1 */;}/** * x509_certificate_parse - Parse a X.509 certificate in DER format * @buf: Pointer to the X.509 certificate in DER format * @len: Buffer length * Returns: Pointer to the parsed certificate or %NULL on failure * * Caller is responsible for freeing the returned certificate by calling * x509_certificate_free(). */struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len){ struct asn1_hdr hdr; const u8 *pos, *end, *hash_start; struct x509_certificate *cert; cert = os_zalloc(sizeof(*cert) + len); if (cert == NULL) return NULL; os_memcpy(cert + 1, buf, len); cert->cert_start = (u8 *) (cert + 1); cert->cert_len = len; pos = buf; end = buf + len; /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ /* Certificate ::= SEQUENCE */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " "a valid SEQUENCE - found class %d tag 0x%x", hdr.class, hdr.tag); x509_certificate_free(cert); return NULL; } pos = hdr.payload; if (pos + hdr.length > end) { x509_certificate_free(cert); return NULL; } if (pos + hdr.length < end) { wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " "encoded certificate", pos + hdr.length, end - pos + hdr.length); end = pos + hdr.length; } hash_start = pos; cert->tbs_cert_start = cert->cert_start + (hash_start - buf); if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { x509_certificate_free(cert); return NULL; } cert->tbs_cert_len = pos - hash_start; /* signatureAlgorithm AlgorithmIdentifier */ if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature_alg, &pos)) { x509_certificate_free(cert); return NULL; } /* signatureValue BIT STRING */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_BITSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " "(signatureValue) - found class %d tag 0x%x", hdr.class, hdr.tag); x509_certificate_free(cert); return NULL; } if (hdr.length < 1) { x509_certificate_free(cert); return NULL; } pos = hdr.payload; if (*pos) { wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", *pos); /* PKCS #1 v1.5 10.2.1: * It is an error if the length in bits of the signature S is * not a multiple of eight. */ x509_certificate_free(cert); return NULL; } os_free(cert->sign_value); cert->sign_value = os_malloc(hdr.length - 1); if (cert->sign_value == NULL) { wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " "signatureValue"); x509_certificate_free(cert); return NULL; } os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); cert->sign_value_len = hdr.length - 1; wpa_hexdump(MSG_MSGDUMP, "X509: signature", cert->sign_value, cert->sign_value_len); return cert;}/** * x509_certificate_check_signature - Verify certificate signature * @issuer: Issuer certificate * @cert: Certificate to be verified * Returns: 0 if cert has a valid signature that was signed by the issuer, * -1 if not */int x509_certificate_check_signature(struct x509_certificate *issuer, struct x509_certificate *cert){ struct crypto_public_key *pk; u8 *data; const u8 *pos, *end, *next, *da_end; size_t data_len; struct asn1_hdr hdr; struct asn1_oid oid; u8 hash[20]; size_t hash_len; if (!x509_pkcs_oid(&cert->signature.oid) || cert->signature.oid.len != 7 || cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " "algorithm"); return -1; } pk = crypto_public_key_import(issuer->public_key, issuer->public_key_len); if (pk == NULL) return -1; data_len = cert->sign_value_len; data = os_malloc(data_len); if (data == NULL) { crypto_public_key_free(pk); return -1; } if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, cert->sign_value_len, data, &data_len) < 0) { wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); crypto_public_key_free(pk); os_free(data); return -1; } crypto_public_key_free(pk); wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); /* * PKCS #1 v1.5, 10.1.2: * * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest * } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING * */ if (asn1_get_next(data, data_len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(DigestInfo) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } pos = hdr.payload; end = pos + hdr.length; /* * X.509: * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } da_end = hdr.payload + hdr.length; if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); os_free(data); return -1; } if (x509_sha1_oid(&oid)) { if (cert->signature.oid.oid[6] != 5 /* sha-1WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " "does not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } goto skip_digest_oid; } if (!x509_digest_oid(&oid)) { wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); os_free(data); return -1; } switch (oid.oid[5]) { case 5: /* md5 */ if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " "not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } break; case 2: /* md2 */ case 4: /* md4 */ default: wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " "(%lu)", oid.oid[5]); os_free(data); return -1; }skip_digest_oid: /* Digest ::= OCTET STRING */ pos = da_end; end = data + data_len; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " "(Digest) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", hdr.payload, hdr.length); switch (cert->signature.oid.oid[6]) { case 4: /* md5WithRSAEncryption */ md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 16; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", hash, hash_len); break; case 5: /* sha-1WithRSAEncryption */ sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 20; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", hash, hash_len); break; case 2: /* md2WithRSAEncryption */ case 11: /* sha256WithRSAEncryption */ case 12: /* sha384WithRSAEncryption */ case 13: /* sha512WithRSAEncryption */ default: wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " "algorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } if (hdr.length != hash_len || os_memcmp(hdr.payload, hash, hdr.length) != 0) { wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " "with calculated tbsCertificate hash"); os_free(data); return -1; } os_free(data); wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " "calculated tbsCertificate hash"); return 0;}static int x509_valid_issuer(const struct x509_certificate *cert){ if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && !cert->ca) { wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " "issuer"); return -1; } if (cert->version == X509_CERT_V3 && !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " "include BasicConstraints extension"); return -1; } if ((cert->extensions_present & X509_EXT_KEY_USAGE) && !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " "keyCertSign bit in Key Usage"); return -1; } return 0;}/** * x509_certificate_chain_validate - Validate X.509 certificate chain * @trusted: List of trusted certificates * @chain: Certificate chain to be validated (first chain must be issued by * signed by the second certificate in the chain and so on) * @reason: Buffer for returning failure reason (X509_VALIDATE_*) * Returns: 0 if chain is valid, -1 if not */int x509_certificate_chain_validate(struct x509_certificate *trusted, struct x509_certificate *chain, int *reason){ long unsigned idx; int chain_trusted = 0; struct x509_certificate *cert, *trust; char buf[128]; struct os_time now; *reason = X509_VALIDATE_OK; wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); os_get_time(&now); for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { x509_name_string(&cert->subject, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); if (chain_trusted) continue; if ((unsigned long) now.sec < (unsigned long) cert->not_before || (unsigned long) now.sec > (unsigned long) cert->not_after) { wpa_printf(MSG_INFO, "X509: Certificate not valid " "(now=%lu not_before=%lu not_after=%lu)", now.sec, cert->not_before, cert->not_after); *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; return -1; } if (cert->next) { if (x509_name_compare(&cert->issuer, &cert->next->subject) != 0) { wpa_printf(MSG_DEBUG, "X509: Certificate " "chain issuer name mismatch"); *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; return -1; } if (x509_valid_issuer(cert->next) < 0) { *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if ((cert->next->extensions_present & X509_EXT_PATH_LEN_CONSTRAINT) && idx > cert->next->path_len_constraint) { wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" " not met (idx=%lu issuer " "pathLenConstraint=%lu)", idx, cert->next->path_len_constraint); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if (x509_certificate_check_signature(cert->next, cert) < 0) { wpa_printf(MSG_DEBUG, "X509: Invalid " "certificate signature within " "chain"); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } } for (trust = trusted; trust; trust = trust->next) { if (x509_name_compare(&cert->issuer, &trust->subject) == 0) break; } if (trust) { wpa_printf(MSG_DEBUG, "X509: Found issuer from the " "list of trusted certificates"); if (x509_valid_issuer(trust) < 0) { *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if (x509_certificate_check_signature(trust, cert) < 0) { wpa_printf(MSG_DEBUG, "X509: Invalid " "certificate signature"); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } wpa_printf(MSG_DEBUG, "X509: Trusted certificate " "found to complete the chain"); chain_trusted = 1; } } if (!chain_trusted) { wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " "from the list of trusted certificates"); if (trusted) { *reason = X509_VALIDATE_UNKNOWN_CA; return -1; } wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " "disabled - ignore unknown CA issue"); } wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); return 0;}/** * x509_certificate_get_subject - Get a certificate based on Subject name * @chain: Certificate chain to search through * @name: Subject name to search for * Returns: Pointer to the certificate with the given Subject name or * %NULL on failure */struct x509_certificate *x509_certificate_get_subject(struct x509_certificate *chain, struct x509_name *name){ struct x509_certificate *cert; for (cert = chain; cert; cert = cert->next) { if (x509_name_compare(&cert->subject, name) == 0) return cert; } return NULL;}/** * x509_certificate_self_signed - Is the certificate self-signed? * @cert: Certificate * Returns: 1 if certificate is self-signed, 0 if not */int x509_certificate_self_signed(struct x509_certificate *cert){ return x509_name_compare(&cert->issuer, &cert->subject) == 0;}#endif /* CONFIG_INTERNAL_X509 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -