static int dh_cms_encrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; EVP_CIPHER_CTX *ctx; int keylen; X509_ALGOR *talg, *wrap_alg = NULL; ASN1_OBJECT *aoid; ASN1_BIT_STRING *pubkey; ASN1_STRING *wrap_str; ASN1_OCTET_STRING *ukm; unsigned char *penc = NULL, *dukm = NULL; int penclen; size_t dukmlen = 0; int rv = 0; int kdf_type, wrap_nid; const EVP_MD *kdf_md; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pctx) return 0; /* Get ephemeral key */ pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, NULL, NULL, NULL)) goto err; X509_ALGOR_get0(&aoid, NULL, NULL, talg); /* Is everything uninitialised? */ if (aoid == OBJ_nid2obj(NID_undef)) { ASN1_INTEGER *pubk; pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL); if (!pubk) goto err; /* Set the key */ penclen = i2d_ASN1_INTEGER(pubk, &penc); ASN1_INTEGER_free(pubk); if (penclen <= 0) goto err; ASN1_STRING_set0(pubkey, penc, penclen); pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber), V_ASN1_UNDEF, NULL); } /* See if custom paraneters set */ kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx); if (kdf_type <= 0) goto err; if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md)) goto err; if (kdf_type == EVP_PKEY_DH_KDF_NONE) { kdf_type = EVP_PKEY_DH_KDF_X9_42; if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0) goto err; } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42) /* Unknown KDF */ goto err; if (kdf_md == NULL) { /* Only SHA1 supported */ kdf_md = EVP_sha1(); if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0) goto err; } else if (EVP_MD_type(kdf_md) != NID_sha1) /* Unsupported digest */ goto err; if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) goto err; /* Get wrap NID */ ctx = CMS_RecipientInfo_kari_get0_ctx(ri); wrap_nid = EVP_CIPHER_CTX_type(ctx); if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0) goto err; keylen = EVP_CIPHER_CTX_key_length(ctx); /* Package wrap algorithm in an AlgorithmIdentifier */ wrap_alg = X509_ALGOR_new(); if (!wrap_alg) goto err; wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); wrap_alg->parameter = ASN1_TYPE_new(); if (!wrap_alg->parameter) goto err; if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) goto err; if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { ASN1_TYPE_free(wrap_alg->parameter); wrap_alg->parameter = NULL; } if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 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; /* * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter * of another AlgorithmIdentifier. */ penc = NULL; penclen = i2d_X509_ALGOR(wrap_alg, &penc); if (!penc || !penclen) goto err; wrap_str = ASN1_STRING_new(); if (!wrap_str) goto err; ASN1_STRING_set0(wrap_str, penc, penclen); penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH), V_ASN1_SEQUENCE, wrap_str); rv = 1; err: if (penc) OPENSSL_free(penc); if (wrap_alg) X509_ALGOR_free(wrap_alg); return rv; }
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; }
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; EVP_CIPHER_CTX *ctx; int keylen; X509_ALGOR *talg, *wrap_alg = NULL; ASN1_OBJECT *aoid; ASN1_BIT_STRING *pubkey; ASN1_STRING *wrap_str; ASN1_OCTET_STRING *ukm; unsigned char *penc = NULL; int penclen; int rv = 0; int ecdh_nid, kdf_type, kdf_nid, wrap_nid; const EVP_MD *kdf_md; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pctx) return 0; /* Get ephemeral key */ pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, NULL, NULL, NULL)) goto err; X509_ALGOR_get0(&aoid, NULL, NULL, talg); /* Is everything uninitialised? */ if (aoid == OBJ_nid2obj(NID_undef)) { EC_KEY *eckey = pkey->pkey.ec; /* Set the key */ unsigned char *p; penclen = i2o_ECPublicKey(eckey, NULL); if (penclen <= 0) goto err; penc = OPENSSL_malloc(penclen); if (!penc) goto err; p = penc; penclen = i2o_ECPublicKey(eckey, &p); if (penclen <= 0) goto err; ASN1_STRING_set0(pubkey, penc, penclen); pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), V_ASN1_UNDEF, NULL); } /* See if custom paraneters set */ kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx); if (kdf_type <= 0) goto err; if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md)) goto err; ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx); if (ecdh_nid < 0) goto err; else if (ecdh_nid == 0) ecdh_nid = NID_dh_std_kdf; else if (ecdh_nid == 1) ecdh_nid = NID_dh_cofactor_kdf; if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { kdf_type = EVP_PKEY_ECDH_KDF_X9_62; if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) goto err; } else /* Uknown KDF */ goto err; if (kdf_md == NULL) { /* Fixme later for better MD */ kdf_md = EVP_sha1(); if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) goto err; } if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) goto err; /* Lookup NID for KDF+cofactor+digest */ if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid)) goto err; /* Get wrap NID */ ctx = CMS_RecipientInfo_kari_get0_ctx(ri); wrap_nid = EVP_CIPHER_CTX_type(ctx); keylen = EVP_CIPHER_CTX_key_length(ctx); /* Package wrap algorithm in an AlgorithmIdentifier */ wrap_alg = X509_ALGOR_new(); if (!wrap_alg) goto err; wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); wrap_alg->parameter = ASN1_TYPE_new(); if (!wrap_alg->parameter) goto err; if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) goto err; if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { ASN1_TYPE_free(wrap_alg->parameter); wrap_alg->parameter = NULL; } if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) goto err; penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen); if (!penclen) goto err; if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) goto err; penc = NULL; /* * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter * of another AlgorithmIdentifier. */ penclen = i2d_X509_ALGOR(wrap_alg, &penc); if (!penc || !penclen) goto err; wrap_str = ASN1_STRING_new(); if (!wrap_str) goto err; ASN1_STRING_set0(wrap_str, penc, penclen); penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); rv = 1; err: OPENSSL_free(penc); X509_ALGOR_free(wrap_alg); return rv; }
int i2d_RSA_NET(RSA *a, unsigned char **pp, int (*cb)(), int sgckey) { int i,j,l[6]; NETSCAPE_PKEY *pkey; unsigned char buf[256],*zz; unsigned char key[EVP_MAX_KEY_LENGTH]; EVP_CIPHER_CTX ctx; X509_ALGOR *alg=NULL; ASN1_OCTET_STRING os,os2; M_ASN1_I2D_vars(a); if (a == NULL) return(0); #ifdef WIN32 r=r; /* shut the damn compiler up :-) */ #endif os.data=os2.data=NULL; if ((pkey=NETSCAPE_PKEY_new()) == NULL) goto err; if (!ASN1_INTEGER_set(pkey->version,0)) goto err; if (pkey->algor->algorithm != NULL) ASN1_OBJECT_free(pkey->algor->algorithm); pkey->algor->algorithm=OBJ_nid2obj(NID_rsaEncryption); if ((pkey->algor->parameter=ASN1_TYPE_new()) == NULL) goto err; pkey->algor->parameter->type=V_ASN1_NULL; l[0]=i2d_RSAPrivateKey(a,NULL); pkey->private_key->length=l[0]; os2.length=i2d_NETSCAPE_PKEY(pkey,NULL); l[1]=i2d_ASN1_OCTET_STRING(&os2,NULL); if ((alg=X509_ALGOR_new()) == NULL) goto err; if (alg->algorithm != NULL) ASN1_OBJECT_free(alg->algorithm); alg->algorithm=OBJ_nid2obj(NID_rc4); if ((alg->parameter=ASN1_TYPE_new()) == NULL) goto err; alg->parameter->type=V_ASN1_NULL; l[2]=i2d_X509_ALGOR(alg,NULL); l[3]=ASN1_object_size(1,l[2]+l[1],V_ASN1_SEQUENCE); #ifndef CONST_STRICT os.data=(unsigned char *)"private-key"; #endif os.length=11; l[4]=i2d_ASN1_OCTET_STRING(&os,NULL); l[5]=ASN1_object_size(1,l[4]+l[3],V_ASN1_SEQUENCE); if (pp == NULL) { if (pkey != NULL) NETSCAPE_PKEY_free(pkey); if (alg != NULL) X509_ALGOR_free(alg); return(l[5]); } if (pkey->private_key->data != NULL) OPENSSL_free(pkey->private_key->data); if ((pkey->private_key->data=(unsigned char *)OPENSSL_malloc(l[0])) == NULL) { ASN1err(ASN1_F_I2D_NETSCAPE_RSA,ERR_R_MALLOC_FAILURE); goto err; } zz=pkey->private_key->data; i2d_RSAPrivateKey(a,&zz); if ((os2.data=(unsigned char *)OPENSSL_malloc(os2.length)) == NULL) { ASN1err(ASN1_F_I2D_NETSCAPE_RSA,ERR_R_MALLOC_FAILURE); goto err; } zz=os2.data; i2d_NETSCAPE_PKEY(pkey,&zz); if (cb == NULL) cb=EVP_read_pw_string; i=cb(buf,256,"Enter Private Key password:"******"SGCKEYSALT", 10); i = 26; } EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf,i,1,key,NULL); memset(buf,0,256); EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit(&ctx,EVP_rc4(),key,NULL); EVP_EncryptUpdate(&ctx,os2.data,&i,os2.data,os2.length); EVP_EncryptFinal(&ctx,&(os2.data[i]),&j); EVP_CIPHER_CTX_cleanup(&ctx); p= *pp; ASN1_put_object(&p,1,l[4]+l[3],V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); i2d_ASN1_OCTET_STRING(&os,&p); ASN1_put_object(&p,1,l[2]+l[1],V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); i2d_X509_ALGOR(alg,&p); i2d_ASN1_OCTET_STRING(&os2,&p); ret=l[5]; err: if (os2.data != NULL) OPENSSL_free(os2.data); if (alg != NULL) X509_ALGOR_free(alg); if (pkey != NULL) NETSCAPE_PKEY_free(pkey); r=r; return(ret); }