static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg, X509_ALGOR **pmaskHash) { const unsigned char *p; int plen; RSA_PSS_PARAMS *pss; *pmaskHash = NULL; if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE) return NULL; p = alg->parameter->value.sequence->data; plen = alg->parameter->value.sequence->length; pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen); if (!pss) return NULL; if (pss->maskGenAlgorithm) { ASN1_TYPE *param = pss->maskGenAlgorithm->parameter; if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) == NID_mgf1 && param->type == V_ASN1_SEQUENCE) { p = param->value.sequence->data; plen = param->value.sequence->length; *pmaskHash = d2i_X509_ALGOR(NULL, &p, plen); } } return pss; }
static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) { int rv = 0; X509_ALGOR *alg, *kekalg = NULL; ASN1_OCTET_STRING *ukm; const unsigned char *p; unsigned char *der = NULL; int plen, keylen; const EVP_CIPHER *kekcipher; EVP_CIPHER_CTX *kekctx; if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) return 0; if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) { ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR); return 0; } if (alg->parameter->type != V_ASN1_SEQUENCE) return 0; p = alg->parameter->value.sequence->data; plen = alg->parameter->value.sequence->length; kekalg = d2i_X509_ALGOR(NULL, &p, plen); if (!kekalg) goto err; kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); if (!kekctx) goto err; kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) goto err; if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) goto err; if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) goto err; keylen = EVP_CIPHER_CTX_key_length(kekctx); if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) goto err; plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen); if (!plen) goto err; if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0) goto err; der = NULL; rv = 1; err: if (kekalg) X509_ALGOR_free(kekalg); if (der) OPENSSL_free(der); return rv; }
static int test_EVP_DigestVerifyInitFromAlgorithm(void) { int ret = 0; CBS cert, cert_body, tbs_cert, algorithm, signature; uint8_t padding; X509_ALGOR *algor = NULL; const uint8_t *derp; EVP_PKEY *pkey = NULL; EVP_MD_CTX md_ctx; EVP_MD_CTX_init(&md_ctx); CBS_init(&cert, kExamplePSSCert, sizeof(kExamplePSSCert)); if (!CBS_get_asn1(&cert, &cert_body, CBS_ASN1_SEQUENCE) || CBS_len(&cert) != 0 || !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) || !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) || CBS_len(&cert_body) != 0) { fprintf(stderr, "Failed to parse certificate\n"); goto out; } /* Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the leading phase byte is just a zero. */ if (!CBS_get_u8(&signature, &padding) || padding != 0) { fprintf(stderr, "Invalid signature padding\n"); goto out; } derp = CBS_data(&algorithm); if (!d2i_X509_ALGOR(&algor, &derp, CBS_len(&algorithm)) || derp != CBS_data(&algorithm) + CBS_len(&algorithm)) { fprintf(stderr, "Failed to parse algorithm\n"); } pkey = load_example_rsa_key(); if (pkey == NULL || !EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) || !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert), CBS_len(&tbs_cert)) || !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), CBS_len(&signature))) { goto out; } ret = 1; out: if (!ret) { BIO_print_errors_fp(stderr); } EVP_MD_CTX_cleanup(&md_ctx); if (pkey) { EVP_PKEY_free(pkey); } return ret; }
/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */ static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) { if (alg == NULL || alg->parameter == NULL || OBJ_obj2nid(alg->algorithm) != NID_mgf1 || alg->parameter->type != V_ASN1_SEQUENCE) { return NULL; } const uint8_t *p = alg->parameter->value.sequence->data; int plen = alg->parameter->value.sequence->length; return d2i_X509_ALGOR(NULL, &p, plen); }
/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */ static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) { const unsigned char *p; int plen; if (alg == NULL || alg->parameter == NULL) return NULL; if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) return NULL; if (alg->parameter->type != V_ASN1_SEQUENCE) return NULL; p = alg->parameter->value.sequence->data; plen = alg->parameter->value.sequence->length; return d2i_X509_ALGOR(NULL, &p, plen); }
static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) { int rv = 0; X509_ALGOR *alg, *kekalg = NULL; ASN1_OCTET_STRING *ukm; const unsigned char *p; unsigned char *dukm = NULL; size_t dukmlen = 0; int keylen, plen; const EVP_CIPHER *kekcipher; EVP_CIPHER_CTX *kekctx; if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) goto err; /* * For DH we only have one OID permissible. If ever any more get defined * we will need something cleverer. */ if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) { DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR); goto err; } if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0) goto err; if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0) goto err; if (alg->parameter->type != V_ASN1_SEQUENCE) goto err; p = alg->parameter->value.sequence->data; plen = alg->parameter->value.sequence->length; kekalg = d2i_X509_ALGOR(NULL, &p, plen); if (!kekalg) goto err; kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); if (!kekctx) goto err; kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) goto err; if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) goto err; if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) goto err; keylen = EVP_CIPHER_CTX_key_length(kekctx); if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0) goto err; /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */ if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(EVP_CIPHER_type(kekcipher))) <= 0) goto err; if (ukm) { dukmlen = ASN1_STRING_length(ukm); dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen); if (!dukm) goto err; } if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0) goto err; dukm = NULL; rv = 1; err: if (kekalg) X509_ALGOR_free(kekalg); if (dukm) OPENSSL_free(dukm); return rv; }
/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a * PKCS#12 structure. */ static int PKCS12_handle_content_info(CBS *content_info, unsigned depth, struct pkcs12_context *ctx) { CBS content_type, wrapped_contents, contents, content_infos; int nid, ret = 0; if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) || !CBS_get_asn1(content_info, &wrapped_contents, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA); goto err; } nid = OBJ_cbs2nid(&content_type); if (nid == NID_pkcs7_encrypted) { /* See https://tools.ietf.org/html/rfc2315#section-13. * * PKCS#7 encrypted data inside a PKCS#12 structure is generally an * encrypted certificate bag and it's generally encrypted with 40-bit * RC2-CBC. */ CBS version_bytes, eci, contents_type, ai, encrypted_contents; X509_ALGOR *algor = NULL; const uint8_t *inp; uint8_t *out; size_t out_len; if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) || /* EncryptedContentInfo, see * https://tools.ietf.org/html/rfc2315#section-10.1 */ !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) || /* AlgorithmIdentifier, see * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */ !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&eci, &encrypted_contents, CBS_ASN1_CONTEXT_SPECIFIC | 0)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } inp = CBS_data(&ai); algor = d2i_X509_ALGOR(NULL, &inp, CBS_len(&ai)); if (algor == NULL) { goto err; } if (inp != CBS_data(&ai) + CBS_len(&ai)) { X509_ALGOR_free(algor); OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (!pbe_crypt(algor, ctx->password, ctx->password_len, CBS_data(&encrypted_contents), CBS_len(&encrypted_contents), &out, &out_len, 0 /* decrypt */)) { X509_ALGOR_free(algor); goto err; } X509_ALGOR_free(algor); CBS_init(&content_infos, out, out_len); ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx); OPENSSL_free(out); } else if (nid == NID_pkcs7_data) { CBS octet_string_contents; if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents, CBS_ASN1_OCTETSTRING)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx); } else if (nid == NID_pkcs8ShroudedKeyBag) { /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section * 4.2.2. */ const uint8_t *inp = CBS_data(&wrapped_contents); PKCS8_PRIV_KEY_INFO *pki = NULL; X509_SIG *encrypted = NULL; if (*ctx->out_key) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12); goto err; } /* encrypted isn't actually an X.509 signature, but it has the same * structure as one and so |X509_SIG| is reused to store it. */ encrypted = d2i_X509_SIG(NULL, &inp, CBS_len(&wrapped_contents)); if (encrypted == NULL) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); X509_SIG_free(encrypted); goto err; } pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len); X509_SIG_free(encrypted); if (pki == NULL) { goto err; } *ctx->out_key = EVP_PKCS82PKEY(pki); PKCS8_PRIV_KEY_INFO_free(pki); if (ctx->out_key == NULL) { goto err; } ret = 1; } else if (nid == NID_certBag) { CBS cert_bag, cert_type, wrapped_cert, cert; if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) || !CBS_get_asn1(&cert_bag, &wrapped_cert, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) { const uint8_t *inp = CBS_data(&cert); X509 *x509 = d2i_X509(NULL, &inp, CBS_len(&cert)); if (!x509) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); goto err; } if (inp != CBS_data(&cert) + CBS_len(&cert)) { OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info, PKCS8_R_BAD_PKCS12_DATA); X509_free(x509); goto err; } if (0 == sk_X509_push(ctx->out_certs, x509)) { X509_free(x509); goto err; } } ret = 1; } else { /* Unknown element type - ignore it. */ ret = 1; } err: return ret; }
int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, int en_de) { CMS_EncryptedContentInfo *ec; CMS_PasswordRecipientInfo *pwri; const unsigned char *p = NULL; int plen; int r = 0; X509_ALGOR *algtmp, *kekalg = NULL; EVP_CIPHER_CTX kekctx; const EVP_CIPHER *kekcipher; unsigned char *key = NULL; size_t keylen; ec = cms->d.envelopedData->encryptedContentInfo; pwri = ri->d.pwri; EVP_CIPHER_CTX_init(&kekctx); if (!pwri->pass) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD); return 0; } algtmp = pwri->keyEncryptionAlgorithm; if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); return 0; } if (algtmp->parameter->type == V_ASN1_SEQUENCE) { p = algtmp->parameter->value.sequence->data; plen = algtmp->parameter->value.sequence->length; kekalg = d2i_X509_ALGOR(NULL, &p, plen); } if (kekalg == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); return 0; } kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); if (!kekcipher) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER); goto err; } /* Fixup cipher based on AlgorithmIdentifier to set IV etc */ if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de)) goto err; EVP_CIPHER_CTX_set_padding(&kekctx, 0); if (EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } algtmp = pwri->keyDerivationAlgorithm; /* Finish password based key derivation to setup key in "ctx" */ if (EVP_PBE_CipherInit(algtmp->algorithm, (char *)pwri->pass, pwri->passlen, algtmp->parameter, &kekctx, en_de) < 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB); goto err; } /* Finally wrap/unwrap the key */ if (en_de) { if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx)) goto err; key = malloc(keylen); if (!key) goto err; if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx)) goto err; pwri->encryptedKey->data = key; pwri->encryptedKey->length = keylen; } else { key = malloc(pwri->encryptedKey->length); if (!key) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (!kek_unwrap_key(key, &keylen, pwri->encryptedKey->data, pwri->encryptedKey->length, &kekctx)) { CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE); goto err; } ec->key = key; ec->keylen = keylen; } r = 1; err: EVP_CIPHER_CTX_cleanup(&kekctx); if (!r && key) free(key); X509_ALGOR_free(kekalg); return r; }
int main (int ac, char **av) { FILE *f_in; FILE *f_out; UINT32 proofLen; BYTE *proof; BYTE *pub; UINT32 pubLen; BYTE *certs; UINT32 certsLen; UINT32 certLen; BYTE key[128/8]; BYTE iv[16]; BYTE asymPlain[8 + sizeof(key) + SHA_DIGEST_LENGTH]; unsigned char oaepPad[4] = "TCPA"; BYTE *asymPadded; UINT32 asymPaddedLength; BYTE *asymEnc; UINT32 asymEncLength; BYTE *chal; UINT32 chalLen; BYTE *symEnc; UINT32 symEncLength; BYTE *symAttest; UINT32 symAttestLength; EVP_CIPHER_CTX ctx; X509 *ekX509; X509_NAME *ekSubj; EVP_PKEY *ekPkey; RSA *ekRsa; RSA *aikRsa; UINT32 tt[1]; int trousersIVMode = 1; int out1, out2; int nCerts; int result; if (ac != 5) { fprintf (stderr, "Usage: %s secretfile aikprooffile outchallengefile outrsafile\n", av[0]); exit (1); } /* Read challenge */ if ((f_in = fopen (av[1], "rb")) == NULL) { fprintf (stderr, "Unable to open file %s\n", av[1]); exit (1); } fseek (f_in, 0, SEEK_END); chalLen = ftell (f_in); fseek (f_in, 0, SEEK_SET); chal = malloc (chalLen); if (fread (chal, 1, chalLen, f_in) != chalLen) { fprintf (stderr, "Unable to read file %s\n", av[1]); exit (1); } fclose (f_in); /* Read AIK proof */ if ((f_in = fopen (av[2], "rb")) == NULL) { fprintf (stderr, "Unable to open file %s\n", av[2]); exit (1); } fseek (f_in, 0, SEEK_END); proofLen = ftell (f_in); fseek (f_in, 0, SEEK_SET); proof = malloc (proofLen); if (fread (proof, 1, proofLen, f_in) != proofLen) { fprintf (stderr, "Unable to read file %s\n", av[2]); exit (1); } fclose (f_in); if (proofLen < 3) goto badproof; pubLen = ntohl (*(UINT32*)proof); if (pubLen + 4 + 4 > proofLen) goto badproof; pub = proof + 4; proof += pubLen+4; proofLen -= pubLen+4; certsLen = ntohl (*(UINT32*)proof); if (certsLen + 4 != proofLen) goto badproof; proof += 4; certs = proof; nCerts = 0; for ( ; ; ) { ++nCerts; if (certsLen < 3) goto badproof; certLen = (proof[0]<<16) | (proof[1]<<8) | proof[2]; if (certLen + 3 > certsLen) goto badproof; proof += certLen + 3; certsLen -= certLen + 3; if (certsLen == 0) break; } if (verifyCertChain (trustedRoot, sizeof(trustedRoot), nCerts, certs) != 0) { fprintf (stderr, "Unable to validate certificate chain in proof file\n"); exit (1); } /* Pull endorsement key from 1st cert */ certLen = (certs[0]<<16) | (certs[1]<<8) | certs[2]; certs += 3; if ((ekX509 = d2i_X509 (NULL, (unsigned char const **)&certs, certLen)) == NULL) goto badproof; /* One last check: EK certs must have empty subject fields */ if ((ekSubj = X509_get_subject_name (ekX509)) == NULL) goto badproof; if (X509_NAME_entry_count (ekSubj) != 0) goto badproof; /* OpenSSL can't parse EK key due to OAEP OID - fix it */ { X509_PUBKEY *pk = X509_get_X509_PUBKEY(ekX509); int algbufLen = i2d_X509_ALGOR(pk->algor, NULL); unsigned char *algbuf = malloc(algbufLen); unsigned char *algbufPtr = algbuf; i2d_X509_ALGOR(pk->algor, &algbufPtr); if (algbuf[12] == 7) algbuf[12] = 1; algbufPtr = algbuf; d2i_X509_ALGOR(&pk->algor, (void *)&algbufPtr, algbufLen); free (algbuf); } if ((ekPkey = X509_get_pubkey (ekX509)) == NULL) goto badproof; if ((ekRsa = EVP_PKEY_get1_RSA (ekPkey)) == NULL) goto badproof; /* Construct encrypted output challenge */ RAND_bytes (key, sizeof(key)); RAND_bytes (iv, sizeof(iv)); /* Prepare buffer to be RSA encrypted to endorsement key */ ((UINT32 *)asymPlain)[0] = htonl(TPM_ALG_AES); ((UINT16 *)asymPlain)[2] = htons(TPM_ES_SYM_CBC_PKCS5PAD); ((UINT16 *)asymPlain)[3] = htons(sizeof(key)); memcpy (asymPlain+8, key, sizeof(key)); SHA1 (pub, pubLen, asymPlain + 8 + sizeof(key)); /* Encrypt to EK */ /* Must use custom padding for TPM to decrypt it */ asymPaddedLength = asymEncLength = RSA_size (ekRsa); asymPadded = malloc (asymPaddedLength); asymEnc = malloc (asymEncLength); RSA_padding_add_PKCS1_OAEP(asymPadded, asymPaddedLength, asymPlain, sizeof(asymPlain), oaepPad, sizeof(oaepPad)); RSA_public_encrypt (asymPaddedLength, asymPadded, asymEnc, ekRsa, RSA_NO_PADDING); free (asymPadded); asymPadded = NULL; /* Encrypt challenge with key */ symEnc = malloc (chalLen + sizeof(iv)); EVP_CIPHER_CTX_init (&ctx); EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), key, iv); EVP_EncryptUpdate (&ctx, symEnc, &out1, chal, chalLen); EVP_EncryptFinal_ex (&ctx, symEnc+out1, &out2); EVP_CIPHER_CTX_cleanup(&ctx); symEncLength = out1 + out2; /* Create TPM_SYM_CA_ATTESTATION struct to hold encrypted cert */ symAttestLength = 28 + sizeof(iv) + symEncLength; symAttest = malloc (symAttestLength); ((UINT32 *)symAttest)[0] = htonl(symEncLength); ((UINT32 *)symAttest)[1] = htonl(TPM_ALG_AES); ((UINT16 *)symAttest)[4] = htons(TPM_ES_SYM_CBC_PKCS5PAD); ((UINT16 *)symAttest)[5] = htons(TPM_SS_NONE); ((UINT32 *)symAttest)[3] = htonl(12+sizeof(iv)); ((UINT32 *)symAttest)[4] = htonl(128); /* Key length in bits */ ((UINT32 *)symAttest)[5] = htonl(sizeof(iv)); /* Block size in bytes */ ((UINT32 *)symAttest)[6] = htonl(sizeof(iv)); /* IV size in bytes */ memcpy (symAttest+28, iv, sizeof(iv)); memcpy (symAttest+28+sizeof(iv), symEnc, symEncLength); if (trousersIVMode) { ((UINT32 *)symAttest)[0] = htonl(symEncLength + sizeof(iv)); ((UINT32 *)symAttest)[3] = htonl(12); /* Take IV to be start of symEnc */ ((UINT32 *)symAttest)[6] = htonl(0); /* IV size in bytes */ } free (symEnc); symEnc = NULL; if ((f_out = fopen (av[3], "wb")) == NULL) { fprintf (stderr, "Unable to open file %s for output\n", av[3]); exit (1); } /* Precede the two blocks with 4-byte lengths */ tt[0] = htonl (asymEncLength); fwrite (tt, 1, sizeof(UINT32), f_out); fwrite (asymEnc, 1, asymEncLength, f_out); tt[0] = htonl (symAttestLength); fwrite (tt, 1, sizeof(UINT32), f_out); if (fwrite (symAttest, 1, symAttestLength, f_out) != symAttestLength) { fprintf (stderr, "Unable to write to file %s\n", av[3]); exit (1); } fclose (f_out); /* Output RSA key representing the AIK for future use */ if ((f_out = fopen (av[4], "wb")) == NULL) { fprintf (stderr, "Unable to open file %s for output\n", av[4]); exit (1); } aikRsa = RSA_new(); aikRsa->n = BN_bin2bn (pub+pubLen-256, 256, NULL); aikRsa->e = BN_new(); BN_set_word (aikRsa->e, 0x10001); if (PEM_write_RSA_PUBKEY(f_out, aikRsa) < 0) { fprintf (stderr, "Unable to write to file %s\n", av[3]); exit (1); } fclose (f_out); printf ("Success!\n"); return 0; badproof: fprintf (stderr, "Input AIK proof file incorrect format\n"); return 1; }