/* * Compare two certificates: they must be identical for this to work. NB: * Although "cmp" operations are generally prototyped to take "const" * arguments (eg. for use in STACKs), the way X509 handling is - these * operations may involve ensuring the hashes are up-to-date and ensuring * certain cert information is cached. So this is the point where the * "depth-first" constification tree has to halt with an evil cast. */ int X509_cmp(const X509 *a, const X509 *b) { /* ensure hash is valid */ X509_check_purpose((X509 *)a, -1, 0); X509_check_purpose((X509 *)b, -1, 0); return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); }
int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert) { X509_check_purpose(cert, -1, -1); if (!cert->skid) return -1; return ASN1_OCTET_STRING_cmp(keyid, cert->skid); }
void openssl_x509_purpose() { BIO *b; int len; FILE *fp; X509 *x, *y; const unsigned char *p; unsigned char buf[MAX5_LEN]; fp = fopen(U1CERTF, "rb"); len = fread(buf, 1, MAX5_LEN, fp); fclose(fp); p = buf; x = X509_new(); y = d2i_X509(&x, &p, len); b = BIO_new(BIO_s_file()); BIO_set_fp(b, stdout, BIO_NOCLOSE); printf("\nX509_Purpose info:\n"); X509_print(b, x); X509_check_purpose(x, X509_PURPOSE_OCSP_HELPER, 0); BIO_free(b); X509_free(x); }
/* * Name: is_ca_cert * Desc: Determines if a given certificate has the attributes * of a CA certificate * Returns: B_TRUE if certificate has attributes of a CA cert * B_FALSE otherwise */ static boolean_t is_ca_cert(X509 *x) { /* * X509_check_purpose causes the extensions that we * care about to be decoded and stored in the X509 * structure, so we must call it first * before checking for CA extensions in the X509 * structure */ (void) X509_check_purpose(x, X509_PURPOSE_ANY, 0); /* keyUsage if present should allow cert signing */ if ((x->ex_flags & EXFLAG_KUSAGE) && !(x->ex_kusage & KU_KEY_CERT_SIGN)) { return (B_FALSE); } /* If basicConstraints says not a CA then say so */ if (x->ex_flags & EXFLAG_BCONS) { if (!(x->ex_flags & EXFLAG_CA)) { return (B_FALSE); } } /* no explicit not-a-CA flags set, so assume that it is */ return (B_TRUE); }
/** * Check if certificate can be used as a CA to sign standard X509 certs * Return 1 if true; 0 if not. */ int verify_x509IsCA(X509 *cert) { int idret; /* final argument to X509_check_purpose() is whether to check for CAness */ idret = X509_check_purpose(cert, X509_PURPOSE_SSL_CLIENT, 1); if (idret == 1) return 1; else if (idret == 0) return 0; else { verify_log( L_WARN, "Purpose warning code = %d", idret ); return 1; } #if 0 BASIC_CONSTRAINTS * x509v3_bc = NULL; int index = -1; int critical; if((x509v3_bc = X509_get_ext_d2i(cert, NID_basic_constraints, &critical, &index)) && x509v3_bc->ca) { *type = GLOBUS_GSI_CERT_UTILS_TYPE_CA; goto exit; } #endif }
uint32_t X509_get_extended_key_usage(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(x, -1, -1); if (x->ex_flags & EXFLAG_XKUSAGE) return x->ex_xkusage; return UINT32_MAX; }
static int trust_compat(X509_TRUST *trust, X509 *x, int flags) { X509_check_purpose(x, -1, 0); if (x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED; else return X509_TRUST_UNTRUSTED; }
long X509_get_pathlen(X509 *x) { /* Called for side effect of caching extensions */ if (X509_check_purpose(x, -1, -1) != 1 || (x->ex_flags & EXFLAG_BCONS) == 0) return -1; return x->ex_pathlen; }
/* * Compare two certificates: they must be identical for this to work. NB: * Although "cmp" operations are generally prototyped to take "const" * arguments (eg. for use in STACKs), the way X509 handling is - these * operations may involve ensuring the hashes are up-to-date and ensuring * certain cert information is cached. So this is the point where the * "depth-first" constification tree has to halt with an evil cast. */ int X509_cmp(const X509 *a, const X509 *b) { int rv; /* ensure hash is valid */ X509_check_purpose((X509 *)a, -1, 0); X509_check_purpose((X509 *)b, -1, 0); rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); if (rv) return rv; /* Check for match against stored encoding too */ if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) { rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len); if (rv) return rv; return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc, a->cert_info->enc.len); } return rv; }
int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer) { if (X509_check_purpose(signer, X509_PURPOSE_TIMESTAMP_SIGN, 0) != 1) { TSerr(TS_F_TS_RESP_CTX_SET_SIGNER_CERT, TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE); return 0; } X509_free(ctx->signer_cert); ctx->signer_cert = signer; CRYPTO_add(&ctx->signer_cert->references, +1, CRYPTO_LOCK_X509); return 1; }
int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer) { if (X509_check_purpose(signer, X509_PURPOSE_TIMESTAMP_SIGN, 0) != 1) { TSerr(TS_F_TS_RESP_CTX_SET_SIGNER_CERT, TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE); return 0; } X509_free(ctx->signer_cert); ctx->signer_cert = signer; X509_up_ref(ctx->signer_cert); return 1; }
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) { int id, i, idret; char *pname; id = X509_PURPOSE_get_id(pt); pname = X509_PURPOSE_get0_name(pt); for (i = 0; i < 2; i++) { idret = X509_check_purpose(cert, id, i); BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); if (idret == 1) BIO_printf(bio, "Yes\n"); else if (idret == 0) BIO_printf(bio, "No\n"); else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); } return 1; }
int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) { int ret; if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) { ret = X509_NAME_cmp(sid->d.issuerAndSerialNumber->issuer, X509_get_issuer_name(cert)); if (ret) return ret; return ASN1_INTEGER_cmp(sid->d.issuerAndSerialNumber->serialNumber, X509_get_serialNumber(cert)); } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { X509_check_purpose(cert, -1, -1); if (!cert->skid) return -1; return ASN1_OCTET_STRING_cmp(sid->d.subjectKeyIdentifier, cert->skid); } else return -1; }
int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) { ASN1_OCTET_STRING *keyid = NULL; X509_check_purpose(cert, -1, -1); if (!cert->skid) { CMSerr(CMS_F_CMS_SET1_KEYID, CMS_R_CERTIFICATE_HAS_NO_KEYID); return 0; } keyid = ASN1_STRING_dup(cert->skid); if (!keyid) { CMSerr(CMS_F_CMS_SET1_KEYID, ERR_R_MALLOC_FAILURE); return 0; } if (*pkeyid) ASN1_OCTET_STRING_free(*pkeyid); *pkeyid = keyid; return 1; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_GetCertificateThumbprint *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_GetCertificateThumbprint( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_ByteString* a_pCertificateThumbprint) { X509* pX509Certificate = OpcUa_Null; const unsigned char* pTemp = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_GetCertificateThumbprint"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate->Data); OpcUa_ReturnErrorIfArgumentNull(a_pCertificateThumbprint); /* SHA-1 produces 20 bytes */ a_pCertificateThumbprint->Length = sizeof(pX509Certificate->sha1_hash); if(a_pCertificateThumbprint->Data == OpcUa_Null) { OpcUa_ReturnStatusCode; } /* d2i_X509 modifies the given pointer -> use local replacement */ pTemp = a_pCertificate->Data; d2i_X509(&pX509Certificate, &pTemp, a_pCertificate->Length); if(pX509Certificate == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* update pX509Certificate->sha1_hash */ X509_check_purpose(pX509Certificate, -1, 0); uStatus = OpcUa_P_Memory_MemCpy(a_pCertificateThumbprint->Data, a_pCertificateThumbprint->Length, pX509Certificate->sha1_hash, sizeof(pX509Certificate->sha1_hash)); X509_free(pX509Certificate); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
extern "C" int32_t X509CheckPurpose(X509* x, int32_t id, int32_t ca) { return X509_check_purpose(x, id, ca); }
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) { CMS_SignedData *sd; CMS_SignerInfo *si = NULL; X509_ALGOR *alg; int i, type; if (!X509_check_private_key(signer, pk)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } sd = cms_signed_data_init(cms); if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); if (!si) goto merr; /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(signer, -1, -1); X509_up_ref(signer); EVP_PKEY_up_ref(pk); si->pkey = pk; si->signer = signer; si->mctx = EVP_MD_CTX_new(); si->pctx = NULL; if (si->mctx == NULL) { CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); goto err; } if (flags & CMS_USE_KEYID) { si->version = 3; if (sd->version < 3) sd->version = 3; type = CMS_SIGNERINFO_KEYIDENTIFIER; } else { type = CMS_SIGNERINFO_ISSUER_SERIAL; si->version = 1; } if (!cms_set1_SignerIdentifier(si->sid, signer, type)) goto err; if (md == NULL) { int def_nid; if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) goto err; md = EVP_get_digestbynid(def_nid); if (md == NULL) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); goto err; } } if (!md) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); goto err; } X509_ALGOR_set_md(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { const ASN1_OBJECT *aoid; alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); X509_ALGOR_get0(&aoid, NULL, NULL, alg); if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) break; } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { alg = X509_ALGOR_new(); if (alg == NULL) goto merr; X509_ALGOR_set_md(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); goto merr; } } if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) goto err; if (!(flags & CMS_NOATTR)) { /* * Initialize signed attributes structure so other attributes * such as signing time etc are added later even if we add none here. */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); if (!si->signedAttrs) goto merr; } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); if (!i) goto merr; } if (flags & CMS_REUSE_DIGEST) { if (!cms_copy_messageDigest(cms, si)) goto err; if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) && !CMS_SignerInfo_sign(si)) goto err; } } if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ if (!CMS_add1_cert(cms, signer)) goto merr; } if (flags & CMS_KEY_PARAM) { if (flags & CMS_NOATTR) { si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL); if (si->pctx == NULL) goto err; if (EVP_PKEY_sign_init(si->pctx) <= 0) goto err; if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0) goto err; } else if (EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, pk) <= 0) goto err; } if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) goto merr; return si; merr: CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); err: M_ASN1_free_of(si, CMS_SignerInfo); return NULL; }
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) { CMS_SignedData *sd; CMS_SignerInfo *si = NULL; X509_ALGOR *alg; int i, type; if (!X509_check_private_key(signer, pk)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } sd = cms_signed_data_init(cms); if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); if (!si) goto merr; X509_check_purpose(signer, -1, -1); CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); si->pkey = pk; si->signer = signer; if (flags & CMS_USE_KEYID) { si->version = 3; if (sd->version < 3) sd->version = 3; type = CMS_SIGNERINFO_KEYIDENTIFIER; } else { type = CMS_SIGNERINFO_ISSUER_SERIAL; si->version = 1; } if (!cms_set1_SignerIdentifier(si->sid, signer, type)) goto err; if (md == NULL) { int def_nid; if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) goto err; md = EVP_get_digestbynid(def_nid); if (md == NULL) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); goto err; } } if (!md) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); goto err; } cms_DigestAlgorithm_set(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { ASN1_OBJECT *aoid; alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); X509_ALGOR_get0(&aoid, NULL, NULL, alg); if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) break; } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { alg = X509_ALGOR_new(); if (!alg) goto merr; cms_DigestAlgorithm_set(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); goto merr; } } if (pk->ameth && pk->ameth->pkey_ctrl) { i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN, 0, si); if (i == -2) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (i <= 0) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE); goto err; } } if (!(flags & CMS_NOATTR)) { /* * Initialialize signed attributes strutucture so other attributes * such as signing time etc are added later even if we add none here. */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); if (!si->signedAttrs) goto merr; } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); if (!i) goto merr; } if (flags & CMS_REUSE_DIGEST) { if (!cms_copy_messageDigest(cms, si)) goto err; if (!(flags & CMS_PARTIAL) && !CMS_SignerInfo_sign(si)) goto err; } } if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ if (!CMS_add1_cert(cms, signer)) goto merr; } if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) goto merr; return si; merr: CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); err: if (si) M_ASN1_free_of(si, CMS_SignerInfo); return NULL; }
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags) { CMS_RecipientInfo *ri = NULL; CMS_KeyTransRecipientInfo *ktri; CMS_EnvelopedData *env; EVP_PKEY *pk = NULL; int i, type; env = cms_get0_enveloped(cms); if (!env) goto err; /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; /* Initialize and add key transport recipient info */ ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); if (!ri->d.ktri) goto merr; ri->type = CMS_RECIPINFO_TRANS; ktri = ri->d.ktri; X509_check_purpose(recip, -1, -1); pk = X509_get_pubkey(recip); if (!pk) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); goto err; } CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); ktri->pkey = pk; ktri->recip = recip; if (flags & CMS_USE_KEYID) { ktri->version = 2; if (env->version < 2) env->version = 2; type = CMS_RECIPINFO_KEYIDENTIFIER; } else { ktri->version = 0; type = CMS_RECIPINFO_ISSUER_SERIAL; } /* * Not a typo: RecipientIdentifier and SignerIdentifier are the same * structure. */ if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) goto err; if (pk->ameth && pk->ameth->pkey_ctrl) { i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE, 0, ri); if (i == -2) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (i <= 0) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_CTRL_FAILURE); goto err; } } if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; return ri; merr: CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); err: if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); return NULL; }
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; }
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags) { CMS_RecipientInfo *ri = NULL; CMS_KeyTransRecipientInfo *ktri; CMS_EnvelopedData *env; EVP_PKEY *pk = NULL; int type; env = cms_get0_enveloped(cms); if (!env) goto err; /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; /* Initialize and add key transport recipient info */ ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); if (!ri->d.ktri) goto merr; ri->type = CMS_RECIPINFO_TRANS; ktri = ri->d.ktri; X509_check_purpose(recip, -1, -1); pk = X509_get_pubkey(recip); if (!pk) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); goto err; } CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); ktri->pkey = pk; ktri->recip = recip; if (flags & CMS_USE_KEYID) { ktri->version = 2; type = CMS_RECIPINFO_KEYIDENTIFIER; } else { ktri->version = 0; type = CMS_RECIPINFO_ISSUER_SERIAL; } /* Not a typo: RecipientIdentifier and SignerIdentifier are the * same structure. */ if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) goto err; /* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8, * hard code algorithm parameters. */ if (pk->type == EVP_PKEY_RSA) { X509_ALGOR_set0(ktri->keyEncryptionAlgorithm, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); } else { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; return ri; merr: CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); err: if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); return NULL; }
int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits, uint32_t *flags) { X509_check_purpose(x, -1, -1); return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags); }
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; }
extern "C" int32_t CryptoNative_X509CheckPurpose(X509* x, int32_t id, int32_t ca) { return X509_check_purpose(x, id, ca); }
/** @brief Extracts data from a certificate store object. @param pCertificate [in] The certificate to examine. @param pIssuer [out, optional] The issuer name of the certificate. @param pSubject [out, optional] The subject name of the certificate. @param pSubjectUri [out, optional] The subject's URI of the certificate. @param pSubjectIP [out, optional] The subject's IP of the certificate. @param pSubjectDNS [out, optional] The subject's DNS name of the certificate. @param pCertThumbprint [out, optional] The thumbprint of the certificate. @param pSubjectHash [out, optional] The hash code of the certificate. @param pCertRawLength [out, optional] The length of the DER encoded data. can be smaller than the total length of pCertificate in case of chain certificate or garbage follow. */ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ExtractCertificateData( OpcUa_ByteString* a_pCertificate, OpcUa_ByteString* a_pIssuer, OpcUa_ByteString* a_pSubject, OpcUa_ByteString* a_pSubjectUri, OpcUa_ByteString* a_pSubjectIP, OpcUa_ByteString* a_pSubjectDNS, OpcUa_ByteString* a_pCertThumbprint, OpcUa_UInt32* a_pSubjectHash, OpcUa_UInt32* a_pCertRawLength) { X509* pX509Cert = OpcUa_Null; char* pName = OpcUa_Null; GENERAL_NAMES* pNames = OpcUa_Null; const unsigned char* p; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ExtractCertificateData"); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); if(a_pIssuer != OpcUa_Null) { a_pIssuer->Data = OpcUa_Null; a_pIssuer->Length = 0; } if(a_pSubject != OpcUa_Null) { a_pSubject->Data = OpcUa_Null; a_pSubject->Length = 0; } if(a_pSubjectUri != OpcUa_Null) { a_pSubjectUri->Data = OpcUa_Null; a_pSubjectUri->Length = 0; } if(a_pSubjectIP != OpcUa_Null) { a_pSubjectIP->Data = OpcUa_Null; a_pSubjectIP->Length = 0; } if(a_pSubjectDNS != OpcUa_Null) { a_pSubjectDNS->Data = OpcUa_Null; a_pSubjectDNS->Length = 0; } if(a_pCertThumbprint != OpcUa_Null) { a_pCertThumbprint->Data = OpcUa_Null; a_pCertThumbprint->Length = 0; } if(a_pSubjectHash != OpcUa_Null) { *a_pSubjectHash = 0; } if(a_pCertRawLength != OpcUa_Null) { *a_pCertRawLength = 0; } /* convert openssl X509 certificate to DER encoded bytestring certificate */ p = a_pCertificate->Data; if(!(pX509Cert = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(a_pIssuer != OpcUa_Null) { pName = X509_NAME_oneline(X509_get_issuer_name(pX509Cert), NULL, 0); OpcUa_GotoErrorIfAllocFailed(pName); a_pIssuer->Length = strlen(pName)+1; a_pIssuer->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pIssuer->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pIssuer->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pIssuer->Data, a_pIssuer->Length, pName, a_pIssuer->Length); OpcUa_GotoErrorIfBad(uStatus); OPENSSL_free(pName); pName = OpcUa_Null; } if(a_pSubject != OpcUa_Null) { pName = X509_NAME_oneline(X509_get_subject_name(pX509Cert), NULL, 0); OpcUa_GotoErrorIfAllocFailed(pName); a_pSubject->Length = strlen(pName)+1; a_pSubject->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubject->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubject->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubject->Data, a_pSubject->Length, pName, a_pSubject->Length); OpcUa_GotoErrorIfBad(uStatus); OPENSSL_free(pName); pName = OpcUa_Null; } if(a_pSubjectUri != OpcUa_Null || a_pSubjectIP != OpcUa_Null || a_pSubjectDNS != OpcUa_Null) { pNames = X509_get_ext_d2i(pX509Cert, NID_subject_alt_name, OpcUa_Null, OpcUa_Null); if (pNames != OpcUa_Null) { int num; for (num = 0; num < sk_GENERAL_NAME_num(pNames); num++) { GENERAL_NAME *value = sk_GENERAL_NAME_value(pNames, num); switch (value->type) { case GEN_URI: if (a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data == OpcUa_Null) { a_pSubjectUri->Length = value->d.ia5->length+1; a_pSubjectUri->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectUri->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectUri->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectUri->Data, a_pSubjectUri->Length, value->d.ia5->data, a_pSubjectUri->Length); OpcUa_GotoErrorIfBad(uStatus); } break; case GEN_IPADD: if (a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data == OpcUa_Null) { a_pSubjectIP->Length = value->d.ip->length; a_pSubjectIP->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectIP->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectIP->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectIP->Data, a_pSubjectIP->Length, value->d.ip->data, a_pSubjectIP->Length); OpcUa_GotoErrorIfBad(uStatus); } break; case GEN_DNS: if (a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data == OpcUa_Null) { a_pSubjectDNS->Length = value->d.ia5->length+1; a_pSubjectDNS->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectDNS->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectDNS->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectDNS->Data, a_pSubjectDNS->Length, value->d.ia5->data, a_pSubjectDNS->Length); OpcUa_GotoErrorIfBad(uStatus); } break; } } sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); pNames = OpcUa_Null; } } if(a_pCertThumbprint != OpcUa_Null) { /* update pX509Cert->sha1_hash */ X509_check_purpose(pX509Cert, -1, 0); a_pCertThumbprint->Length = sizeof(pX509Cert->sha1_hash); a_pCertThumbprint->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertThumbprint->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pCertThumbprint->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pCertThumbprint->Data, a_pCertThumbprint->Length, pX509Cert->sha1_hash, a_pCertThumbprint->Length); OpcUa_GotoErrorIfBad(uStatus); } if(a_pSubjectHash != OpcUa_Null) { *a_pSubjectHash = X509_NAME_hash(X509_get_subject_name(pX509Cert)); } if(a_pCertRawLength != OpcUa_Null) { *a_pCertRawLength = (OpcUa_UInt32)(p - a_pCertificate->Data); } X509_free(pX509Cert); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(a_pIssuer != OpcUa_Null && a_pIssuer->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pIssuer->Data); a_pIssuer->Data = OpcUa_Null; a_pIssuer->Length = 0; } if(a_pSubject != OpcUa_Null && a_pSubject->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubject->Data); a_pSubject->Data = OpcUa_Null; a_pSubject->Length = 0; } if(a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectUri->Data); a_pSubjectUri->Data = OpcUa_Null; a_pSubjectUri->Length = 0; } if(a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectIP->Data); a_pSubjectIP->Data = OpcUa_Null; a_pSubjectIP->Length = 0; } if(a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectDNS->Data); a_pSubjectDNS->Data = OpcUa_Null; a_pSubjectDNS->Length = 0; } if(a_pCertThumbprint != OpcUa_Null && a_pCertThumbprint->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pCertThumbprint->Data); a_pCertThumbprint->Data = OpcUa_Null; a_pCertThumbprint->Length = 0; } if (pName != OpcUa_Null) { OPENSSL_free(pName); } if (pNames != OpcUa_Null) { sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); } if(pX509Cert != OpcUa_Null) { X509_free(pX509Cert); } OpcUa_FinishErrorHandling; }
const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(x, -1, -1); return x->skid; }
static int itacns_add_cert(sc_pkcs15_card_t *p15card, int type, int authority, const sc_path_t *path, const sc_pkcs15_id_t *id, const char *label, int obj_flags, int *ext_info_ok, int *key_usage, int *x_key_usage) { int r; /* const char *label = "Certificate"; */ sc_pkcs15_cert_info_t info; sc_pkcs15_object_t obj; #ifdef ENABLE_OPENSSL X509 *x509; sc_pkcs15_cert_t *cert; #endif SC_FUNC_CALLED(p15card->card->ctx, 1); if(type != SC_PKCS15_TYPE_CERT_X509) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Cannot add a certificate of a type other than X.509"); return 1; } *ext_info_ok = 0; memset(&info, 0, sizeof(info)); memset(&obj, 0, sizeof(obj)); info.id = *id; info.authority = authority; if (path) info.path = *path; strlcpy(obj.label, label, sizeof(obj.label)); obj.flags = obj_flags; r = sc_pkcs15emu_add_x509_cert(p15card, &obj, &info); SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r, "Could not add X.509 certificate"); /* If we have OpenSSL, read keyUsage */ #ifdef ENABLE_OPENSSL r = sc_pkcs15_read_certificate(p15card, &info, &cert); SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r, "Could not read X.509 certificate"); { const u8 *throwaway = cert->data.value; x509 = d2i_X509(NULL, &throwaway, cert->data.len); } sc_pkcs15_free_certificate(cert); if (!x509) return SC_SUCCESS; X509_check_purpose(x509, -1, 0); if(x509->ex_flags & EXFLAG_KUSAGE) { *ext_info_ok = 1; *key_usage = x509->ex_kusage; *x_key_usage = x509->ex_xkusage; } OPENSSL_free(x509); return SC_SUCCESS; #else /* ENABLE_OPENSSL */ return SC_SUCCESS; #endif /* ENABLE_OPENSSL */ }
const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(x, -1, -1); return (x->akid != NULL ? x->akid->keyid : NULL); }
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) { CMS_SignedData *sd; CMS_SignerInfo *si = NULL; X509_ALGOR *alg; int i, type; if(!X509_check_private_key(signer, pk)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } sd = cms_signed_data_init(cms); if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); if (!si) goto merr; X509_check_purpose(signer, -1, -1); CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); si->pkey = pk; si->signer = signer; if (flags & CMS_USE_KEYID) { si->version = 3; if (sd->version < 3) sd->version = 3; type = CMS_SIGNERINFO_KEYIDENTIFIER; } else { type = CMS_SIGNERINFO_ISSUER_SERIAL; si->version = 1; } if (!cms_set1_SignerIdentifier(si->sid, signer, type)) goto err; /* Since no EVP_PKEY_METHOD in 0.9.8 hard code SHA1 as default */ if (md == NULL) md = EVP_sha1(); /* OpenSSL 0.9.8 only supports SHA1 with non-RSA keys */ if ((pk->type != EVP_PKEY_RSA) && (EVP_MD_type(md) != NID_sha1)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } cms_DigestAlgorithm_set(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { ASN1_OBJECT *aoid; alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); X509_ALGOR_get0(&aoid, NULL, NULL, alg); if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) break; } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { alg = X509_ALGOR_new(); if (!alg) goto merr; cms_DigestAlgorithm_set(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); goto merr; } } /* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8, * hard code algorithm parameters. */ switch (pk->type) { case EVP_PKEY_RSA: X509_ALGOR_set0(si->signatureAlgorithm, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); break; case EVP_PKEY_DSA: X509_ALGOR_set0(si->signatureAlgorithm, OBJ_nid2obj(NID_dsaWithSHA1), V_ASN1_UNDEF, 0); break; case EVP_PKEY_EC: X509_ALGOR_set0(si->signatureAlgorithm, OBJ_nid2obj(NID_ecdsa_with_SHA1), V_ASN1_UNDEF, 0); break; default: CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (!(flags & CMS_NOATTR)) { /* Initialialize signed attributes strutucture so other * attributes such as signing time etc are added later * even if we add none here. */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); if (!si->signedAttrs) goto merr; } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); if (!i) goto merr; } if (flags & CMS_REUSE_DIGEST) { if (!cms_copy_messageDigest(cms, si)) goto err; if (!(flags & CMS_PARTIAL) && !CMS_SignerInfo_sign(si)) goto err; } } if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ if (!CMS_add1_cert(cms, signer)) goto merr; } if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) goto merr; return si; merr: CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); err: if (si) M_ASN1_free_of(si, CMS_SignerInfo); return NULL; }
uint32_t X509_get_extension_flags(X509 *x) { /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(x, -1, -1); return x->ex_flags; }