/* * Encrypt a blob with the private key of the certificate * passed as a parameter. */ static DATA_BLOB *encrypt_blob_pk(struct torture_context *tctx, TALLOC_CTX *mem_ctx, uint8_t *cert_data, uint32_t cert_len, DATA_BLOB *to_encrypt) { hx509_context hctx; hx509_cert cert; heim_octet_string secretdata; heim_octet_string encrypted; heim_oid encryption_oid; DATA_BLOB *blob; int hret; hx509_context_init(&hctx); hret = hx509_cert_init_data(hctx, cert_data, cert_len, &cert); if (hret) { torture_comment(tctx, "error while loading the cert\n"); hx509_context_free(&hctx); return NULL; } secretdata.data = to_encrypt->data; secretdata.length = to_encrypt->length; hret = hx509_cert_public_encrypt(hctx, &secretdata, cert, &encryption_oid, &encrypted); hx509_cert_free(cert); hx509_context_free(&hctx); if (hret) { torture_comment(tctx, "error while encrypting\n"); return NULL; } blob = talloc_zero(mem_ctx, DATA_BLOB); if (blob == NULL) { der_free_oid(&encryption_oid); der_free_octet_string(&encrypted); return NULL; } *blob = data_blob_talloc(blob, encrypted.data, encrypted.length); der_free_octet_string(&encrypted); der_free_oid(&encryption_oid); if (blob->data == NULL) { return NULL; } return blob; }
static int encryptedData_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { heim_octet_string content; heim_oid contentType; int ret; memset(&contentType, 0, sizeof(contentType)); ret = hx509_cms_decrypt_encrypted(context, _hx509_collector_get_lock(c), data, length, &contentType, &content); if (ret) return ret; if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) ret = parse_safe_content(context, c, content.data, content.length); der_free_octet_string(&content); der_free_oid(&contentType); return ret; }
static int ShroudedKeyBag_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { PKCS8EncryptedPrivateKeyInfo pk; heim_octet_string content; int ret; memset(&pk, 0, sizeof(pk)); ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL); if (ret) return ret; ret = _hx509_pbe_decrypt(context, _hx509_collector_get_lock(c), &pk.encryptionAlgorithm, &pk.encryptedData, &content); free_PKCS8EncryptedPrivateKeyInfo(&pk); if (ret) return ret; ret = keyBag_parser(context, c, content.data, content.length, attrs); der_free_octet_string(&content); return ret; }
static int certBag_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { heim_octet_string os; hx509_cert cert; PKCS12_CertBag cb; int ret; ret = decode_PKCS12_CertBag(data, length, &cb, NULL); if (ret) return ret; if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) { free_PKCS12_CertBag(&cb); return 0; } ret = decode_PKCS12_OctetString(cb.certValue.data, cb.certValue.length, &os, NULL); free_PKCS12_CertBag(&cb); if (ret) return ret; ret = hx509_cert_init_data(context, os.data, os.length, &cert); der_free_octet_string(&os); if (ret) return ret; ret = _hx509_collector_certs_add(context, c, cert); if (ret) { hx509_cert_free(cert); return ret; } { const PKCS12_Attribute *attr; const heim_oid *oids[] = { &asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName }; size_t i; for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) { const heim_oid *oid = oids[i]; attr = find_attribute(attrs, oid); if (attr) _hx509_set_cert_attribute(context, cert, oid, &attr->attrValues); } } hx509_cert_free(cert); return 0; }
static void free_private_key(struct private_key *key) { free_AlgorithmIdentifier(&key->alg); if (key->private_key) hx509_private_key_free(&key->private_key); der_free_octet_string(&key->localKeyId); free(key); }
krb5_error_code _kdc_tkt_add_if_relevant_ad(krb5_context context, EncTicketPart *tkt, int type, const krb5_data *data) { krb5_error_code ret; size_t size = 0; if (tkt->authorization_data == NULL) { tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); if (tkt->authorization_data == NULL) { krb5_set_error_message(context, ENOMEM, "out of memory"); return ENOMEM; } } /* add the entry to the last element */ { AuthorizationData ad = { 0, NULL }; AuthorizationDataElement ade; ade.ad_type = type; ade.ad_data = *data; ret = add_AuthorizationData(&ad, &ade); if (ret) { krb5_set_error_message(context, ret, "add AuthorizationData failed"); return ret; } ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT; ASN1_MALLOC_ENCODE(AuthorizationData, ade.ad_data.data, ade.ad_data.length, &ad, &size, ret); free_AuthorizationData(&ad); if (ret) { krb5_set_error_message(context, ret, "ASN.1 encode of " "AuthorizationData failed"); return ret; } if (ade.ad_data.length != size) krb5_abortx(context, "internal asn.1 encoder error"); ret = add_AuthorizationData(tkt->authorization_data, &ade); der_free_octet_string(&ade.ad_data); if (ret) { krb5_set_error_message(context, ret, "add AuthorizationData failed"); return ret; } } return 0; }
static DATA_BLOB *encrypt_blob(struct torture_context *tctx, TALLOC_CTX *mem_ctx, DATA_BLOB *key, DATA_BLOB *iv, DATA_BLOB *to_encrypt, const AlgorithmIdentifier *alg) { hx509_crypto crypto; hx509_context hctx; heim_octet_string ivos; heim_octet_string *encrypted; DATA_BLOB *blob = talloc_zero(mem_ctx, DATA_BLOB); int res; ivos.data = talloc_array(mem_ctx, uint8_t, iv->length); ivos.length = iv->length; memcpy(ivos.data, iv->data, iv->length); hx509_context_init(&hctx); res = hx509_crypto_init(hctx, NULL, &alg->algorithm, &crypto); if (res) { torture_comment(tctx, "error while doing the init of the crypto object\n"); hx509_context_free(&hctx); return NULL; } res = hx509_crypto_set_key_data(crypto, key->data, key->length); if (res) { torture_comment(tctx, "error while setting the key of the crypto object\n"); hx509_context_free(&hctx); return NULL; } hx509_crypto_set_padding(crypto, HX509_CRYPTO_PADDING_NONE); res = hx509_crypto_encrypt(crypto, to_encrypt->data, to_encrypt->length, &ivos, &encrypted); if (res) { torture_comment(tctx, "error while encrypting\n"); hx509_crypto_destroy(crypto); hx509_context_free(&hctx); return NULL; } *blob = data_blob_talloc(blob, encrypted->data, encrypted->length); der_free_octet_string(encrypted); free(encrypted); hx509_crypto_destroy(crypto); hx509_context_free(&hctx); return blob; }
static int safeContent_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { heim_octet_string os; int ret; ret = decode_PKCS12_OctetString(data, length, &os, NULL); if (ret) return ret; ret = parse_safe_content(context, c, os.data, os.length); der_free_octet_string(&os); return ret; }
static int envelopedData_parser(hx509_context context, struct hx509_collector *c, const void *data, size_t length, const PKCS12_Attributes *attrs) { heim_octet_string content; heim_oid contentType; hx509_lock lock; int ret; memset(&contentType, 0, sizeof(contentType)); lock = _hx509_collector_get_lock(c); ret = hx509_cms_unenvelope(context, _hx509_lock_unlock_certs(lock), 0, data, length, NULL, 0, &contentType, &content); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "PKCS12 failed to unenvelope"); return ret; } if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) ret = parse_safe_content(context, c, content.data, content.length); der_free_octet_string(&content); der_free_oid(&contentType); return ret; }
int hx509_cms_verify_signed(hx509_context context, hx509_verify_ctx ctx, unsigned int flags, const void *data, size_t length, const heim_octet_string *signedContent, hx509_certs pool, heim_oid *contentType, heim_octet_string *content, hx509_certs *signer_certs) { SignerInfo *signer_info; hx509_cert cert = NULL; hx509_certs certs = NULL; SignedData sd; size_t size; int ret, found_valid_sig; size_t i; *signer_certs = NULL; content->data = NULL; content->length = 0; contentType->length = 0; contentType->components = NULL; memset(&sd, 0, sizeof(sd)); ret = decode_SignedData(data, length, &sd, &size); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode SignedData"); goto out; } if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) { ret = HX509_CMS_NO_DATA_AVAILABLE; hx509_set_error_string(context, 0, ret, "No content data in SignedData"); goto out; } if (sd.encapContentInfo.eContent && signedContent) { ret = HX509_CMS_NO_DATA_AVAILABLE; hx509_set_error_string(context, 0, ret, "Both external and internal SignedData"); goto out; } if (sd.encapContentInfo.eContent) ret = der_copy_octet_string(sd.encapContentInfo.eContent, content); else ret = der_copy_octet_string(signedContent, content); if (ret) { hx509_set_error_string(context, 0, ret, "malloc: out of memory"); goto out; } ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer", 0, NULL, &certs); if (ret) goto out; ret = hx509_certs_init(context, "MEMORY:cms-signer-certs", 0, NULL, signer_certs); if (ret) goto out; /* XXX Check CMS version */ ret = any_to_certs(context, &sd, certs); if (ret) goto out; if (pool) { ret = hx509_certs_merge(context, certs, pool); if (ret) goto out; } for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) { heim_octet_string signed_data; const heim_oid *match_oid; heim_oid decode_oid; signer_info = &sd.signerInfos.val[i]; match_oid = NULL; if (signer_info->signature.length == 0) { ret = HX509_CMS_MISSING_SIGNER_DATA; hx509_set_error_string(context, 0, ret, "SignerInfo %d in SignedData " "missing sigature", i); continue; } ret = find_CMSIdentifier(context, &signer_info->sid, certs, _hx509_verify_get_time(ctx), &cert, HX509_QUERY_KU_DIGITALSIGNATURE); if (ret) { /** * If HX509_CMS_VS_NO_KU_CHECK is set, allow more liberal * search for matching certificates by not considering * KeyUsage bits on the certificates. */ if ((flags & HX509_CMS_VS_NO_KU_CHECK) == 0) continue; ret = find_CMSIdentifier(context, &signer_info->sid, certs, _hx509_verify_get_time(ctx), &cert, 0); if (ret) continue; } if (signer_info->signedAttrs) { const Attribute *attr; CMSAttributes sa; heim_octet_string os; sa.val = signer_info->signedAttrs->val; sa.len = signer_info->signedAttrs->len; /* verify that sigature exists */ attr = find_attribute(&sa, &asn1_oid_id_pkcs9_messageDigest); if (attr == NULL) { ret = HX509_CRYPTO_SIGNATURE_MISSING; hx509_set_error_string(context, 0, ret, "SignerInfo have signed attributes " "but messageDigest (signature) " "is missing"); goto next_sigature; } if (attr->value.len != 1) { ret = HX509_CRYPTO_SIGNATURE_MISSING; hx509_set_error_string(context, 0, ret, "SignerInfo have more then one " "messageDigest (signature)"); goto next_sigature; } ret = decode_MessageDigest(attr->value.val[0].data, attr->value.val[0].length, &os, &size); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode " "messageDigest (signature)"); goto next_sigature; } ret = _hx509_verify_signature(context, NULL, &signer_info->digestAlgorithm, content, &os); der_free_octet_string(&os); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to verify messageDigest"); goto next_sigature; } /* * Fetch content oid inside signedAttrs or set it to * id-pkcs7-data. */ attr = find_attribute(&sa, &asn1_oid_id_pkcs9_contentType); if (attr == NULL) { match_oid = &asn1_oid_id_pkcs7_data; } else { if (attr->value.len != 1) { ret = HX509_CMS_DATA_OID_MISMATCH; hx509_set_error_string(context, 0, ret, "More then one oid in signedAttrs"); goto next_sigature; } ret = decode_ContentType(attr->value.val[0].data, attr->value.val[0].length, &decode_oid, &size); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode " "oid in signedAttrs"); goto next_sigature; } match_oid = &decode_oid; } ASN1_MALLOC_ENCODE(CMSAttributes, signed_data.data, signed_data.length, &sa, &size, ret); if (ret) { if (match_oid == &decode_oid) der_free_oid(&decode_oid); hx509_clear_error_string(context); goto next_sigature; } if (size != signed_data.length) _hx509_abort("internal ASN.1 encoder error"); } else { signed_data.data = content->data; signed_data.length = content->length; match_oid = &asn1_oid_id_pkcs7_data; } /** * If HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH, allow * encapContentInfo mismatch with the oid in signedAttributes * (or if no signedAttributes where use, pkcs7-data oid). * This is only needed to work with broken CMS implementations * that doesn't follow CMS signedAttributes rules. */ if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType) && (flags & HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH) == 0) { ret = HX509_CMS_DATA_OID_MISMATCH; hx509_set_error_string(context, 0, ret, "Oid in message mismatch from the expected"); } if (match_oid == &decode_oid) der_free_oid(&decode_oid); if (ret == 0) { ret = hx509_verify_signature(context, cert, &signer_info->signatureAlgorithm, &signed_data, &signer_info->signature); if (ret) hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to verify signature in " "CMS SignedData"); } if (signer_info->signedAttrs) free(signed_data.data); if (ret) goto next_sigature; /** * If HX509_CMS_VS_NO_VALIDATE flags is set, do not verify the * signing certificates and leave that up to the caller. */ if ((flags & HX509_CMS_VS_NO_VALIDATE) == 0) { ret = hx509_verify_path(context, ctx, cert, certs); if (ret) goto next_sigature; } ret = hx509_certs_add(context, *signer_certs, cert); if (ret) goto next_sigature; found_valid_sig++; next_sigature: if (cert) hx509_cert_free(cert); cert = NULL; } /** * If HX509_CMS_VS_ALLOW_ZERO_SIGNER is set, allow empty * SignerInfo (no signatures). If SignedData have no signatures, * the function will return 0 with signer_certs set to NULL. Zero * signers is allowed by the standard, but since its only useful * in corner cases, it make into a flag that the caller have to * turn on. */ if (sd.signerInfos.len == 0 && (flags & HX509_CMS_VS_ALLOW_ZERO_SIGNER)) { if (*signer_certs) hx509_certs_free(signer_certs); } else if (found_valid_sig == 0) { if (ret == 0) { ret = HX509_CMS_SIGNER_NOT_FOUND; hx509_set_error_string(context, 0, ret, "No signers where found"); } goto out; } ret = der_copy_oid(&sd.encapContentInfo.eContentType, contentType); if (ret) { hx509_clear_error_string(context); goto out; } out: free_SignedData(&sd); if (certs) hx509_certs_free(&certs); if (ret) { if (content->data) der_free_octet_string(content); if (*signer_certs) hx509_certs_free(signer_certs); der_free_oid(contentType); der_free_octet_string(content); } return ret; }
int hx509_cms_envelope_1(hx509_context context, int flags, hx509_cert cert, const void *data, size_t length, const heim_oid *encryption_type, const heim_oid *contentType, heim_octet_string *content) { KeyTransRecipientInfo *ri; heim_octet_string ivec; heim_octet_string key; hx509_crypto crypto = NULL; int ret, cmsidflag; EnvelopedData ed; size_t size; memset(&ivec, 0, sizeof(ivec)); memset(&key, 0, sizeof(key)); memset(&ed, 0, sizeof(ed)); memset(content, 0, sizeof(*content)); if (encryption_type == NULL) encryption_type = &asn1_oid_id_aes_256_cbc; if ((flags & HX509_CMS_EV_NO_KU_CHECK) == 0) { ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE); if (ret) goto out; } ret = hx509_crypto_init(context, NULL, encryption_type, &crypto); if (ret) goto out; if (flags & HX509_CMS_EV_ALLOW_WEAK) hx509_crypto_allow_weak(crypto); ret = hx509_crypto_set_random_key(crypto, &key); if (ret) { hx509_set_error_string(context, 0, ret, "Create random key for EnvelopedData content"); goto out; } ret = hx509_crypto_random_iv(crypto, &ivec); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to create a random iv"); goto out; } ret = hx509_crypto_encrypt(crypto, data, length, &ivec, &ed.encryptedContentInfo.encryptedContent); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to encrypt EnvelopedData content"); goto out; } { AlgorithmIdentifier *enc_alg; enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm; ret = der_copy_oid(encryption_type, &enc_alg->algorithm); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set crypto oid " "for EnvelopedData"); goto out; } ALLOC(enc_alg->parameters, 1); if (enc_alg->parameters == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Failed to allocate crypto paramaters " "for EnvelopedData"); goto out; } ret = hx509_crypto_get_params(context, crypto, &ivec, enc_alg->parameters); if (ret) { goto out; } } ALLOC_SEQ(&ed.recipientInfos, 1); if (ed.recipientInfos.val == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Failed to allocate recipients info " "for EnvelopedData"); goto out; } ri = &ed.recipientInfos.val[0]; if (flags & HX509_CMS_EV_ID_NAME) { ri->version = 0; cmsidflag = CMS_ID_NAME; } else { ri->version = 2; cmsidflag = CMS_ID_SKI; } ret = fill_CMSIdentifier(cert, cmsidflag, &ri->rid); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set CMS identifier info " "for EnvelopedData"); goto out; } ret = hx509_cert_public_encrypt(context, &key, cert, &ri->keyEncryptionAlgorithm.algorithm, &ri->encryptedKey); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to encrypt transport key for " "EnvelopedData"); goto out; } /* * */ ed.version = 0; ed.originatorInfo = NULL; ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy content oid for " "EnvelopedData"); goto out; } ed.unprotectedAttrs = NULL; ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length, &ed, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to encode EnvelopedData"); goto out; } if (size != content->length) _hx509_abort("internal ASN.1 encoder error"); out: if (crypto) hx509_crypto_destroy(crypto); if (ret) der_free_octet_string(content); der_free_octet_string(&key); der_free_octet_string(&ivec); free_EnvelopedData(&ed); return ret; }
int hx509_cms_unenvelope(hx509_context context, hx509_certs certs, int flags, const void *data, size_t length, const heim_octet_string *encryptedContent, time_t time_now, heim_oid *contentType, heim_octet_string *content) { heim_octet_string key; EnvelopedData ed; hx509_cert cert; AlgorithmIdentifier *ai; const heim_octet_string *enccontent; heim_octet_string *params, params_data; heim_octet_string ivec; size_t size; int ret, matched = 0, findflags = 0; size_t i; memset(&key, 0, sizeof(key)); memset(&ed, 0, sizeof(ed)); memset(&ivec, 0, sizeof(ivec)); memset(content, 0, sizeof(*content)); memset(contentType, 0, sizeof(*contentType)); if ((flags & HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT) == 0) findflags |= HX509_QUERY_KU_ENCIPHERMENT; ret = decode_EnvelopedData(data, length, &ed, &size); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode EnvelopedData"); return ret; } if (ed.recipientInfos.len == 0) { ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; hx509_set_error_string(context, 0, ret, "No recipient info in enveloped data"); goto out; } enccontent = ed.encryptedContentInfo.encryptedContent; if (enccontent == NULL) { if (encryptedContent == NULL) { ret = HX509_CMS_NO_DATA_AVAILABLE; hx509_set_error_string(context, 0, ret, "Content missing from encrypted data"); goto out; } enccontent = encryptedContent; } else if (encryptedContent != NULL) { ret = HX509_CMS_NO_DATA_AVAILABLE; hx509_set_error_string(context, 0, ret, "Both internal and external encrypted data"); goto out; } cert = NULL; for (i = 0; i < ed.recipientInfos.len; i++) { KeyTransRecipientInfo *ri; char *str; int ret2; ri = &ed.recipientInfos.val[i]; ret = find_CMSIdentifier(context, &ri->rid, certs, time_now, &cert, HX509_QUERY_PRIVATE_KEY|findflags); if (ret) continue; matched = 1; /* found a matching certificate, let decrypt */ ret = _hx509_cert_private_decrypt(context, &ri->encryptedKey, &ri->keyEncryptionAlgorithm.algorithm, cert, &key); hx509_cert_free(cert); if (ret == 0) break; /* succuessfully decrypted cert */ cert = NULL; ret2 = unparse_CMSIdentifier(context, &ri->rid, &str); if (ret2 == 0) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to decrypt with %s", str); free(str); } } if (!matched) { ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; hx509_set_error_string(context, 0, ret, "No private key matched any certificate"); goto out; } if (cert == NULL) { ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "No private key decrypted the transfer key"); goto out; } ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy EnvelopedData content oid"); goto out; } ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm; if (ai->parameters) { params_data.data = ai->parameters->data; params_data.length = ai->parameters->length; params = ¶ms_data; } else params = NULL; { hx509_crypto crypto; ret = hx509_crypto_init(context, NULL, &ai->algorithm, &crypto); if (ret) goto out; if (flags & HX509_CMS_UE_ALLOW_WEAK) hx509_crypto_allow_weak(crypto); if (params) { ret = hx509_crypto_set_params(context, crypto, params, &ivec); if (ret) { hx509_crypto_destroy(crypto); goto out; } } ret = hx509_crypto_set_key_data(crypto, key.data, key.length); if (ret) { hx509_crypto_destroy(crypto); hx509_set_error_string(context, 0, ret, "Failed to set key for decryption " "of EnvelopedData"); goto out; } ret = hx509_crypto_decrypt(crypto, enccontent->data, enccontent->length, ivec.length ? &ivec : NULL, content); hx509_crypto_destroy(crypto); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decrypt EnvelopedData"); goto out; } } out: free_EnvelopedData(&ed); der_free_octet_string(&key); if (ivec.length) der_free_octet_string(&ivec); if (ret) { der_free_oid(contentType); der_free_octet_string(content); } return ret; }
static int sig_process(hx509_context context, void *ctx, hx509_cert cert) { struct sigctx *sigctx = ctx; heim_octet_string buf, sigdata = { 0, NULL }; SignerInfo *signer_info = NULL; AlgorithmIdentifier digest; size_t size; void *ptr; int ret; SignedData *sd = &sigctx->sd; hx509_path path; memset(&digest, 0, sizeof(digest)); memset(&path, 0, sizeof(path)); if (_hx509_cert_private_key(cert) == NULL) { hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, "Private key missing for signing"); return HX509_PRIVATE_KEY_MISSING; } if (sigctx->digest_alg) { ret = copy_AlgorithmIdentifier(sigctx->digest_alg, &digest); if (ret) hx509_clear_error_string(context); } else { ret = hx509_crypto_select(context, HX509_SELECT_DIGEST, _hx509_cert_private_key(cert), sigctx->peer, &digest); } if (ret) goto out; /* * Allocate on more signerInfo and do the signature processing */ ptr = realloc(sd->signerInfos.val, (sd->signerInfos.len + 1) * sizeof(sd->signerInfos.val[0])); if (ptr == NULL) { ret = ENOMEM; goto out; } sd->signerInfos.val = ptr; signer_info = &sd->signerInfos.val[sd->signerInfos.len]; memset(signer_info, 0, sizeof(*signer_info)); signer_info->version = 1; ret = fill_CMSIdentifier(cert, sigctx->cmsidflag, &signer_info->sid); if (ret) { hx509_clear_error_string(context); goto out; } signer_info->signedAttrs = NULL; signer_info->unsignedAttrs = NULL; ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm); if (ret) { hx509_clear_error_string(context); goto out; } /* * If it isn't pkcs7-data send signedAttributes */ if (der_heim_oid_cmp(sigctx->eContentType, &asn1_oid_id_pkcs7_data) != 0) { CMSAttributes sa; heim_octet_string sig; ALLOC(signer_info->signedAttrs, 1); if (signer_info->signedAttrs == NULL) { ret = ENOMEM; goto out; } ret = _hx509_create_signature(context, NULL, &digest, &sigctx->content, NULL, &sig); if (ret) goto out; ASN1_MALLOC_ENCODE(MessageDigest, buf.data, buf.length, &sig, &size, ret); der_free_octet_string(&sig); if (ret) { hx509_clear_error_string(context); goto out; } if (size != buf.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_one_attribute(&signer_info->signedAttrs->val, &signer_info->signedAttrs->len, &asn1_oid_id_pkcs9_messageDigest, &buf); if (ret) { free(buf.data); hx509_clear_error_string(context); goto out; } ASN1_MALLOC_ENCODE(ContentType, buf.data, buf.length, sigctx->eContentType, &size, ret); if (ret) goto out; if (size != buf.length) _hx509_abort("internal ASN.1 encoder error"); ret = add_one_attribute(&signer_info->signedAttrs->val, &signer_info->signedAttrs->len, &asn1_oid_id_pkcs9_contentType, &buf); if (ret) { free(buf.data); hx509_clear_error_string(context); goto out; } sa.val = signer_info->signedAttrs->val; sa.len = signer_info->signedAttrs->len; ASN1_MALLOC_ENCODE(CMSAttributes, sigdata.data, sigdata.length, &sa, &size, ret); if (ret) { hx509_clear_error_string(context); goto out; } if (size != sigdata.length) _hx509_abort("internal ASN.1 encoder error"); } else { sigdata.data = sigctx->content.data; sigdata.length = sigctx->content.length; } { AlgorithmIdentifier sigalg; ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG, _hx509_cert_private_key(cert), sigctx->peer, &sigalg); if (ret) goto out; ret = _hx509_create_signature(context, _hx509_cert_private_key(cert), &sigalg, &sigdata, &signer_info->signatureAlgorithm, &signer_info->signature); free_AlgorithmIdentifier(&sigalg); if (ret) goto out; } sigctx->sd.signerInfos.len++; signer_info = NULL; /* * Provide best effort path */ if (sigctx->certs) { unsigned int i; if (sigctx->pool && sigctx->leafonly == 0) { _hx509_calculate_path(context, HX509_CALCULATE_PATH_NO_ANCHOR, time(NULL), sigctx->anchors, 0, cert, sigctx->pool, &path); } else _hx509_path_append(context, &path, cert); for (i = 0; i < path.len; i++) { /* XXX remove dups */ ret = hx509_certs_add(context, sigctx->certs, path.val[i]); if (ret) { hx509_clear_error_string(context); goto out; } } } out: if (signer_info) free_SignerInfo(signer_info); if (sigdata.data != sigctx->content.data) der_free_octet_string(&sigdata); _hx509_path_free(&path); free_AlgorithmIdentifier(&digest); return ret; }
CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { struct session_state *state; struct st_object *o; CK_RV ret; int hret; const AlgorithmIdentifier *alg; heim_octet_string sig, data; INIT_CONTEXT(); st_logf("Sign\n"); VERIFY_SESSION_HANDLE(hSession, &state); sig.data = NULL; sig.length = 0; if (state->sign_object == -1) return CKR_ARGUMENTS_BAD; if (pulSignatureLen == NULL) { st_logf("signature len NULL\n"); ret = CKR_ARGUMENTS_BAD; goto out; } if (pData == NULL_PTR) { st_logf("data NULL\n"); ret = CKR_ARGUMENTS_BAD; goto out; } o = soft_token.object.objs[state->sign_object]; if (hx509_cert_have_private_key(o->cert) == 0) { st_logf("private key NULL\n"); return CKR_ARGUMENTS_BAD; } switch(state->sign_mechanism->mechanism) { case CKM_RSA_PKCS: alg = hx509_signature_rsa_pkcs1_x509(); break; default: ret = CKR_FUNCTION_NOT_SUPPORTED; goto out; } data.data = pData; data.length = ulDataLen; hret = _hx509_create_signature(context, _hx509_cert_private_key(o->cert), alg, &data, NULL, &sig); if (hret) { ret = CKR_DEVICE_ERROR; goto out; } *pulSignatureLen = sig.length; if (pSignature != NULL_PTR) memcpy(pSignature, sig.data, sig.length); ret = CKR_OK; out: if (sig.data) { memset(sig.data, 0, sig.length); der_free_octet_string(&sig); } return ret; }
OM_uint32 _gss_iakerb_acquire_cred_ext(OM_uint32 * minor_status, const gss_name_t desired_name, gss_const_OID credential_type, const void *credential_data, OM_uint32 time_req, gss_const_OID desired_mech, gss_cred_usage_t cred_usage, gss_cred_id_t * output_cred_handle) { krb5_context context; gsskrb5_cred handle; krb5_error_code ret; krb5_creds cred; gss_buffer_t credential_buffer = NULL; #ifdef PKINIT hx509_cert cert = NULL; #endif memset(&cred, 0, sizeof(cred)); if (cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) return GSS_S_FAILURE; GSSAPI_KRB5_INIT_STATUS(&context, status); /* pick up the credential */ if (gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { credential_buffer = (gss_buffer_t)credential_data; if (credential_buffer->length + 1 < credential_buffer->length) return GSS_S_FAILURE; #ifdef PKINIT } else if (gss_oid_equal(credential_type, GSS_C_CRED_CERTIFICATE)) { cert = (hx509_cert)credential_data; } else if (gss_oid_equal(credential_type, GSS_C_CRED_SecIdentity)) { ret = hx509_cert_init_SecFramework(context->hx509ctx, rk_UNCONST(credential_data), &cert); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } #endif } else { *minor_status = KRB5_NOCREDS_SUPPLIED; return GSS_S_FAILURE; } if (desired_name == GSS_C_NO_NAME) return GSS_S_FAILURE; handle = calloc(1, sizeof(*handle)); if (handle == NULL) return (GSS_S_FAILURE); HEIMDAL_MUTEX_init(&handle->cred_id_mutex); handle->usage = GSS_C_INITIATE; { krb5_principal princ = (krb5_principal)desired_name; ret = krb5_copy_principal(context, princ, &handle->principal); if (ret) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); free(handle); *minor_status = ret; return GSS_S_FAILURE; } } if (credential_buffer) { handle->password = malloc(credential_buffer->length + 1); if (handle->password == NULL) { krb5_free_principal(context, handle->principal); HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); free(handle); *minor_status = ENOMEM; return GSS_S_FAILURE; } memcpy(handle->password, credential_buffer->value, credential_buffer->length); handle->password[credential_buffer->length] = '\0'; } #ifdef PKINIT if (cert) handle->cert = heim_retain(cert); #endif handle->keytab = NULL; handle->ccache = NULL; handle->endtime = INT_MAX; /* * Lets overwrite the same credentials if we already have it */ ret = krb5_cc_cache_match(context, handle->principal, &handle->ccache); if (ret) { ret = krb5_cc_new_unique(context, krb5_cc_type_api, NULL, &handle->ccache); if (ret) goto out; } ret = krb5_cc_initialize(context, handle->ccache, handle->principal); if (ret) goto out; { krb5_data data; krb5_data_zero(&data); krb5_cc_set_config(context, handle->ccache, NULL, "iakerb", &data); } if (handle->password) { krb5_data pw; pw.data = handle->password; pw.length = strlen(handle->password); ret = krb5_cc_set_config(context, handle->ccache, NULL, "password", &pw); if (ret) goto out; } #ifdef PKINIT if (handle->cert) { krb5_data pd; ret = hx509_cert_get_persistent(handle->cert, &pd); if (ret) goto out; ret = krb5_cc_set_config(context, handle->ccache, NULL, "certificate-ref", &pd); der_free_octet_string(&pd); if (ret) goto out; } #endif *output_cred_handle = (gss_cred_id_t) handle; *minor_status = 0; return GSS_S_COMPLETE; out: krb5_free_principal(context, handle->principal); if (handle->password) { memset(handle->password, 0, strlen(handle->password)); free(handle->password); } #ifdef PKINIT if (handle->cert) hx509_cert_free(handle->cert); #endif if (handle->ccache) krb5_cc_destroy(context, handle->ccache); HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); free(handle); *minor_status = ret; return GSS_S_FAILURE; }
void der_free_printable_string (heim_printable_string *str) { der_free_octet_string(str); }
static int ecdsa_create_signature(hx509_context context, const struct signature_alg *sig_alg, const hx509_private_key signer, const AlgorithmIdentifier *alg, const heim_octet_string *data, AlgorithmIdentifier *signatureAlgorithm, heim_octet_string *sig) { const AlgorithmIdentifier *digest_alg; heim_octet_string indata; const heim_oid *sig_oid; unsigned int siglen; int ret; if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0) _hx509_abort("internal error passing private key to wrong ops"); sig_oid = sig_alg->sig_oid; digest_alg = sig_alg->digest_alg; if (signatureAlgorithm) { ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2); if (ret) { hx509_clear_error_string(context); return ret; } } ret = _hx509_create_signature(context, NULL, digest_alg, data, NULL, &indata); if (ret) goto error; sig->length = ECDSA_size(signer->private_key.ecdsa); sig->data = malloc(sig->length); if (sig->data == NULL) { der_free_octet_string(&indata); ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto error; } siglen = sig->length; ret = ECDSA_sign(-1, indata.data, indata.length, sig->data, &siglen, signer->private_key.ecdsa); der_free_octet_string(&indata); if (ret != 1) { ret = HX509_CMS_FAILED_CREATE_SIGATURE; hx509_set_error_string(context, 0, ret, "ECDSA sign failed: %d", ret); goto error; } if (siglen > sig->length) _hx509_abort("ECDSA signature prelen longer the output len"); sig->length = siglen; return 0; error: if (signatureAlgorithm) free_AlgorithmIdentifier(signatureAlgorithm); return ret; }
int hdb_entry_get_password(krb5_context context, HDB *db, const hdb_entry *entry, char **p) { HDB_extension *ext; char *str; int ret; ext = hdb_find_extension(entry, choice_HDB_extension_data_password); if (ext) { heim_utf8_string str; heim_octet_string pw; if (db->hdb_master_key_set && ext->data.u.password.mkvno) { hdb_master_key key; key = _hdb_find_master_key(ext->data.u.password.mkvno, db->hdb_master_key); if (key == NULL) { krb5_set_error_string(context, "master key %d missing", *ext->data.u.password.mkvno); return HDB_ERR_NO_MKEY; } ret = _hdb_mkey_decrypt(context, key, HDB_KU_MKEY, ext->data.u.password.password.data, ext->data.u.password.password.length, &pw); } else { ret = der_copy_octet_string(&ext->data.u.password.password, &pw); } if (ret) { krb5_clear_error_string(context); return ret; } str = pw.data; if (str[pw.length - 1] != '\0') { krb5_set_error_string(context, "password malformated"); return EINVAL; } *p = strdup(str); der_free_octet_string(&pw); if (*p == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } return 0; } ret = krb5_unparse_name(context, entry->principal, &str); if (ret == 0) { krb5_set_error_string(context, "no password attributefor %s", str); free(str); } else krb5_clear_error_string(context); return ENOENT; }
void der_free_ia5_string (heim_ia5_string *str) { der_free_octet_string(str); }
void free_heim_any_set(heim_any_set *data) { der_free_octet_string(data); }
void free_heim_any(heim_any *data) { der_free_octet_string(data); }
static int p12_init(hx509_context context, hx509_certs certs, void **data, int flags, const char *residue, hx509_lock lock) { struct ks_pkcs12 *p12; size_t len; void *buf; PKCS12_PFX pfx; PKCS12_AuthenticatedSafe as; int ret; size_t i; struct hx509_collector *c; *data = NULL; if (lock == NULL) lock = _hx509_empty_lock; ret = _hx509_collector_alloc(context, lock, &c); if (ret) return ret; p12 = calloc(1, sizeof(*p12)); if (p12 == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto out; } p12->fn = strdup(residue); if (p12->fn == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto out; } if (flags & HX509_CERTS_CREATE) { ret = hx509_certs_init(context, "MEMORY:ks-file-create", 0, lock, &p12->certs); if (ret == 0) *data = p12; goto out; } ret = rk_undumpdata(residue, &buf, &len); if (ret) { hx509_clear_error_string(context); goto out; } ret = decode_PKCS12_PFX(buf, len, &pfx, NULL); rk_xfree(buf); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode the PFX in %s", residue); goto out; } if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) { free_PKCS12_PFX(&pfx); ret = EINVAL; hx509_set_error_string(context, 0, ret, "PKCS PFX isn't a pkcs7-data container"); goto out; } if (pfx.authSafe.content == NULL) { free_PKCS12_PFX(&pfx); ret = EINVAL; hx509_set_error_string(context, 0, ret, "PKCS PFX missing data"); goto out; } { heim_octet_string asdata; ret = decode_PKCS12_OctetString(pfx.authSafe.content->data, pfx.authSafe.content->length, &asdata, NULL); free_PKCS12_PFX(&pfx); if (ret) { hx509_clear_error_string(context); goto out; } ret = decode_PKCS12_AuthenticatedSafe(asdata.data, asdata.length, &as, NULL); der_free_octet_string(&asdata); if (ret) { hx509_clear_error_string(context); goto out; } } for (i = 0; i < as.len; i++) parse_pkcs12_type(context, c, &as.val[i].contentType, as.val[i].content->data, as.val[i].content->length, NULL); free_PKCS12_AuthenticatedSafe(&as); ret = _hx509_collector_collect_certs(context, c, &p12->certs); if (ret == 0) *data = p12; out: _hx509_collector_free(c); if (ret && p12) { if (p12->fn) free(p12->fn); if (p12->certs) hx509_certs_free(&p12->certs); free(p12); } return ret; }
static int ecdsa_verify_signature(hx509_context context, const struct signature_alg *sig_alg, const Certificate *signer, const AlgorithmIdentifier *alg, const heim_octet_string *data, const heim_octet_string *sig) { const AlgorithmIdentifier *digest_alg; const SubjectPublicKeyInfo *spi; heim_octet_string digest; int ret; EC_KEY *key = NULL; int groupnid; EC_GROUP *group; const unsigned char *p; long len; digest_alg = sig_alg->digest_alg; ret = _hx509_create_signature(context, NULL, digest_alg, data, NULL, &digest); if (ret) return ret; /* set up EC KEY */ spi = &signer->tbsCertificate.subjectPublicKeyInfo; if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0) return HX509_CRYPTO_SIG_INVALID_FORMAT; /* * Find the group id */ ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid); if (ret) { der_free_octet_string(&digest); return ret; } /* * Create group, key, parse key */ key = EC_KEY_new(); group = EC_GROUP_new_by_curve_name(groupnid); EC_KEY_set_group(key, group); EC_GROUP_free(group); p = spi->subjectPublicKey.data; len = spi->subjectPublicKey.length / 8; if (o2i_ECPublicKey(&key, &p, len) == NULL) { EC_KEY_free(key); return HX509_CRYPTO_SIG_INVALID_FORMAT; } ret = ECDSA_verify(-1, digest.data, digest.length, sig->data, sig->length, key); der_free_octet_string(&digest); EC_KEY_free(key); if (ret != 1) { ret = HX509_CRYPTO_SIG_INVALID_FORMAT; return ret; } return 0; }