static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca) { int i_ext; /* If ca is true we must return if this is a valid CA certificate. */ if (ca) return check_ca(x); /* * Check the optional key usage field: * if Key Usage is present, it must be one of digitalSignature * and/or nonRepudiation (other values are not consistent and shall * be rejected). */ if ((x->ex_flags & EXFLAG_KUSAGE) && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) return 0; /* Only time stamp key usage is permitted and it's required. */ if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) return 0; /* Extended Key Usage MUST be critical */ i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, 0); if (i_ext >= 0) { X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext); if (!X509_EXTENSION_get_critical(ext)) return 0; } return 1; }
/* common S/MIME checks */ static int purpose_smime(const X509 *x, int ca) { if (xku_reject(x, XKU_SMIME)) return 0; if (ca) { int ca_ret; ca_ret = check_ca(x); if (!ca_ret) return 0; /* check nsCertType if present */ if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret; else return 0; } if (x->ex_flags & EXFLAG_NSCERT) { if (x->ex_nscert & NS_SMIME) return 1; /* Workaround for some buggy certificates */ if (x->ex_nscert & NS_SSL_CLIENT) return 2; return 0; } return 1; }
static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) { /* Must be a valid CA. Should we really support the "I don't know" value (2)? */ if(ca) return check_ca(x); /* leaf certificate is checked in OCSP_verify() */ return 1; }
int X509_check_ca(X509 *x) { if(!(x->ex_flags & EXFLAG_SET)) { x509v3_cache_extensions(x); } return check_ca(x); }
/* Check SSL CA: common checks for SSL client and server */ static int check_ssl_ca(const X509 *x) { int ca_ret; ca_ret = check_ca(x); if(!ca_ret) return 0; /* check nsCertType if present */ if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret; else return 0; }
static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca) { if(ca) { int ca_ret; if((ca_ret = check_ca(x)) != 2) return ca_ret; else return 0; } if(ku_reject(x, KU_CRL_SIGN)) return 0; return 1; }
int X509_check_ca(X509 *x) { if(!(x->ex_flags & EXFLAG_SET)) { CRYPTO_w_lock(CRYPTO_LOCK_X509); x509v3_cache_extensions(x); CRYPTO_w_unlock(CRYPTO_LOCK_X509); } return check_ca(x); }
int X509_check_ca(X509 *x) { if (!(x->ex_flags & EXFLAG_SET)) { CRYPTO_THREAD_write_lock(x->lock); x509v3_cache_extensions(x); CRYPTO_THREAD_unlock(x->lock); } return check_ca(x); }
int easy_pkcs7_sign(const char *content, size_t len, char **signature, size_t *signature_len, const char *key_file, const char *cert_file) { FILE *f; X509 *certificate; STACK_OF(X509) *c, *cert_chain; EVP_PKEY *private_key; char *tmp_sig; BIO *out, *in; PKCS7 *p7; int status; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); status = -1; private_key = NULL; cert_chain = NULL; in = NULL; c = file_to_certs(cert_file); if (sk_X509_num(c) != 1) { warnx("More then one certificate in the certificate file"); goto cleanup; } certificate = sk_X509_value(c, 0); /* Compute ex_kusage */ X509_check_purpose(certificate, -1, 0); if (check_ca(certificate)) { warnx("CA keys are not valid for signatures"); goto cleanup; } if (certificate->ex_xkusage != pkg_key_usage) { warnx("Certificate must have CODE SIGNING " "and EMAIL PROTECTION property"); goto cleanup; } if (cert_chain_file) cert_chain = file_to_certs(cert_chain_file); if ((f = fopen(key_file, "r")) == NULL) { warn("Failed to open private key file %s", key_file); goto cleanup; } private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL); fclose(f); if (private_key == NULL) { warnx("Can't read private key: %s", key_file); goto cleanup; } if (X509_check_private_key(certificate, private_key) != 1) { warnx("The private key %s doesn't match the certificate %s", key_file, cert_file); goto cleanup; } in = BIO_new_mem_buf(__UNCONST(content), len); p7 = PKCS7_sign(certificate, private_key, cert_chain, in, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY); if (p7 == NULL) { warnx("Failed to create signature structure"); goto cleanup; } out = BIO_new(BIO_s_mem()); PEM_write_bio_PKCS7(out, p7); *signature_len = BIO_get_mem_data(out, &tmp_sig); *signature = xmalloc(*signature_len); memcpy(*signature, tmp_sig, *signature_len); BIO_free_all(out); PKCS7_free(p7); status = 0; cleanup: sk_X509_free(c); sk_X509_free(cert_chain); EVP_PKEY_free(private_key); BIO_free(in); return status; }
int easy_pkcs7_verify(const char *content, size_t len, const char *signature, size_t signature_len, const char *anchor, int is_pkg) { STACK_OF(X509) *cert_chain, *signers; X509_STORE *store; BIO *sig, *in; PKCS7 *p7; int i, status; X509_NAME *name; char *subject; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); status = -1; if (cert_chain_file) cert_chain = file_to_certs(cert_chain_file); else cert_chain = NULL; store = X509_STORE_new(); if (store == NULL) { sk_X509_free(cert_chain); warnx("Failed to create certificate store"); return -1; } X509_STORE_load_locations(store, anchor, NULL); in = BIO_new_mem_buf(__UNCONST(content), len); sig = BIO_new_mem_buf(__UNCONST(signature), signature_len); signers = NULL; p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL); if (p7 == NULL) { warnx("Failed to parse the signature"); goto cleanup; } if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) { warnx("Failed to verify signature"); goto cleanup; } signers = PKCS7_get0_signers(p7, NULL, 0); if (signers == NULL) { warnx("Failed to get signers"); goto cleanup; } if (sk_X509_num(signers) == 0) { warnx("No signers found"); goto cleanup; } for (i = 0; i < sk_X509_num(signers); i++) { /* Compute ex_xkusage */ X509_check_purpose(sk_X509_value(signers, i), -1, -1); if (check_ca(sk_X509_value(signers, i))) { warnx("CA keys are not valid for signatures"); goto cleanup; } if (is_pkg) { if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) { warnx("Certificate must have CODE SIGNING " "and EMAIL PROTECTION property"); goto cleanup; } } else { if (sk_X509_value(signers, i)->ex_xkusage != 0) { warnx("Certificate must not have any property"); goto cleanup; } } } printf("Sigature ok, signed by:\n"); for (i = 0; i < sk_X509_num(signers); i++) { name = X509_get_subject_name(sk_X509_value(signers, i)); subject = X509_NAME_oneline(name, NULL, 0); printf("\t%s\n", subject); OPENSSL_free(subject); } status = 0; cleanup: sk_X509_free(cert_chain); sk_X509_free(signers); X509_STORE_free(store); PKCS7_free(p7); BIO_free(in); BIO_free(sig); return status; }