uint32_t TSS_Bind(RSA * key, const struct tpm_buffer * data, struct tpm_buffer * blob) { uint32_t ret; unsigned char *blob2 = NULL; int size = RSA_size(key); unsigned char tcpa[] = "TCPA"; blob2 = malloc(size); if (blob2 == NULL) { ret = ERR_MEM_ERR; goto exit; } /* check input arguments */ if (key == NULL || data == NULL || blob == NULL) { ret = ERR_NULL_ARG; goto exit; } ret = RSA_padding_add_PKCS1_OAEP(blob2, size, data->buffer, data->used, tcpa, 4); if (ret != 1) { ret = ERR_CRYPT_ERR; goto exit; } ret = RSA_public_encrypt(size, blob2, blob->buffer, key, RSA_NO_PADDING); if ((int) ret == -1) { ret = ERR_CRYPT_ERR; goto exit; } blob->used = ret; ret = 0; exit: if (blob2) free(blob2); return ret; }
static int RSA_eay_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { BIGNUM *f,*ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; if ((ctx=BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); f = BN_CTX_get(ctx); ret = BN_CTX_get(ctx); num=BN_num_bytes(rsa->n); buf = OPENSSL_malloc(num); if (!f || !ret || !buf) { RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE); goto err; } switch (padding) { case RSA_PKCS1_PADDING: i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen); break; #ifndef OPENSSL_NO_SHA case RSA_PKCS1_OAEP_PADDING: i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0); break; #endif case RSA_SSLV23_PADDING: i=RSA_padding_add_SSLv23(buf,num,from,flen); break; case RSA_NO_PADDING: i=RSA_padding_add_none(buf,num,from,flen); break; default: RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (i <= 0) goto err; if (BN_bin2bn(buf,num,f) == NULL) goto err; if (BN_ucmp(f, rsa->n) >= 0) { /* usually the padding functions would catch this */ RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; /* put in leading 0 bytes if the number is less than the * length of the modulus */ j=BN_num_bytes(ret); i=BN_bn2bin(ret,&(to[num-j])); for (k=0; k<(num-i); k++) to[k]=0; r=num; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (buf != NULL) { OPENSSL_cleanse(buf,num); OPENSSL_free(buf); } return(r); }
unsigned int OpenSSLCryptoKeyRSA::publicEncrypt(const unsigned char * inBuf, unsigned char * cipherBuf, unsigned int inLength, unsigned int maxOutLength, PaddingType padding, hashMethod hm) { // Perform an encrypt if (mp_rsaKey == NULL) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA - Attempt to encrypt data with empty key"); } int encryptSize; switch (padding) { case XSECCryptoKeyRSA::PAD_PKCS_1_5 : encryptSize = RSA_public_encrypt(inLength, #if defined(XSEC_OPENSSL_CONST_BUFFERS) inBuf, #else (unsigned char *) inBuf, #endif cipherBuf, mp_rsaKey, RSA_PKCS1_PADDING); if (encryptSize < 0) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA publicKeyEncrypt - Error performing PKCS1_5 padded RSA encrypt"); } break; case XSECCryptoKeyRSA::PAD_OAEP_MGFP1 : { unsigned char * tBuf; unsigned int num = RSA_size(mp_rsaKey); if (maxOutLength < num) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA publicKeyEncrypt - Not enough space in cipherBuf"); } const EVP_MD* evp_md = NULL; const EVP_MD* mgf_md = NULL; switch (hm) { case HASH_SHA1: evp_md = EVP_get_digestbyname("SHA1"); break; case HASH_SHA224: evp_md = EVP_get_digestbyname("SHA224"); break; case HASH_SHA256: evp_md = EVP_get_digestbyname("SHA256"); break; case HASH_SHA384: evp_md = EVP_get_digestbyname("SHA384"); break; case HASH_SHA512: evp_md = EVP_get_digestbyname("SHA512"); break; } if (evp_md == NULL) { throw XSECCryptoException(XSECCryptoException::MDError, "OpenSSL:RSA - OAEP digest algorithm not supported by this version of OpenSSL"); } switch (m_mgf) { case MGF1_SHA1: mgf_md = EVP_get_digestbyname("SHA1"); break; case MGF1_SHA224: mgf_md = EVP_get_digestbyname("SHA224"); break; case MGF1_SHA256: mgf_md = EVP_get_digestbyname("SHA256"); break; case MGF1_SHA384: mgf_md = EVP_get_digestbyname("SHA384"); break; case MGF1_SHA512: mgf_md = EVP_get_digestbyname("SHA512"); break; } if (mgf_md == NULL) { throw XSECCryptoException(XSECCryptoException::MDError, "OpenSSL:RSA - MGF not supported by this version of OpenSSL"); } XSECnew(tBuf, unsigned char[num]); ArrayJanitor<unsigned char> j_tBuf(tBuf); // First add the padding encryptSize = RSA_padding_add_PKCS1_OAEP(tBuf, num, //#if defined(XSEC_OPENSSL_CONST_BUFFERS) inBuf, //#else // (unsigned char *) inBuf, //#endif inLength, mp_oaepParams, m_oaepParamsLen, evp_md, mgf_md); if (encryptSize <= 0) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA publicKeyEncrypt - Error adding OAEPadding"); } encryptSize = RSA_public_encrypt(num, tBuf, cipherBuf, mp_rsaKey, RSA_NO_PADDING); if (encryptSize < 0) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA publicKeyEncrypt - Error encrypting padded data"); } } break; default : throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA - Unknown padding method"); } return encryptSize; }
static int RSA_eay_public_encrypt(FIPS_RSA_SIZE_T flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { BIGNUM f,ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; BN_init(&f); BN_init(&ret); if(FIPS_selftest_failed()) { FIPSerr(FIPS_F_RSA_EAY_PUBLIC_ENCRYPT,FIPS_R_FIPS_SELFTEST_FAILED); goto err; } if ((ctx=BN_CTX_new()) == NULL) goto err; num=BN_num_bytes(rsa->n); if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL) { RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE); goto err; } switch (padding) { case RSA_PKCS1_PADDING: i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen); break; #ifndef OPENSSL_NO_SHA case RSA_PKCS1_OAEP_PADDING: i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0); break; #endif case RSA_SSLV23_PADDING: i=RSA_padding_add_SSLv23(buf,num,from,flen); break; case RSA_NO_PADDING: i=RSA_padding_add_none(buf,num,from,flen); break; default: RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (i <= 0) goto err; if (BN_bin2bn(buf,num,&f) == NULL) goto err; if (BN_ucmp(&f, rsa->n) >= 0) { /* usually the padding functions would catch this */ RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) { BN_MONT_CTX* bn_mont_ctx; if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) goto err; if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx)) { BN_MONT_CTX_free(bn_mont_ctx); goto err; } if (rsa->_method_mod_n == NULL) /* other thread may have finished first */ { CRYPTO_w_lock(CRYPTO_LOCK_RSA); if (rsa->_method_mod_n == NULL) { rsa->_method_mod_n = bn_mont_ctx; bn_mont_ctx = NULL; } CRYPTO_w_unlock(CRYPTO_LOCK_RSA); } if (bn_mont_ctx) BN_MONT_CTX_free(bn_mont_ctx); } if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; /* put in leading 0 bytes if the number is less than the * length of the modulus */ j=BN_num_bytes(&ret); i=BN_bn2bin(&ret,&(to[num-j])); for (k=0; k<(num-i); k++) to[k]=0; r=num; err: if (ctx != NULL) BN_CTX_free(ctx); BN_clear_free(&f); BN_clear_free(&ret); if (buf != NULL) { OPENSSL_cleanse(buf,num); OPENSSL_free(buf); } return(r); }
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { BIGNUM *f, *ret; int i, j, k, num = 0, r = -1; unsigned char *buf = NULL; BN_CTX *ctx = NULL; if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE); return -1; } if (BN_ucmp(rsa->n, rsa->e) <= 0) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); return -1; } /* for large moduli, enforce exponent limit */ if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) { if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); return -1; } } if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); f = BN_CTX_get(ctx); ret = BN_CTX_get(ctx); num = BN_num_bytes(rsa->n); buf = OPENSSL_malloc(num); if (ret == NULL || buf == NULL) { RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE); goto err; } switch (padding) { case RSA_PKCS1_PADDING: i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); break; case RSA_PKCS1_OAEP_PADDING: i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); break; case RSA_SSLV23_PADDING: i = RSA_padding_add_SSLv23(buf, num, from, flen); break; case RSA_NO_PADDING: i = RSA_padding_add_none(buf, num, from, flen); break; default: RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (i <= 0) goto err; if (BN_bin2bn(buf, num, f) == NULL) goto err; if (BN_ucmp(f, rsa->n) >= 0) { /* usually the padding functions would catch this */ RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) if (!BN_MONT_CTX_set_locked (&rsa->_method_mod_n, rsa->lock, rsa->n, ctx)) goto err; if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx, rsa->_method_mod_n)) goto err; /* * put in leading 0 bytes if the number is less than the length of the * modulus */ j = BN_num_bytes(ret); i = BN_bn2bin(ret, &(to[num - j])); for (k = 0; k < (num - i); k++) to[k] = 0; r = num; err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_clear_free(buf, num); return r; }
uint32_t TPM_TakeOwnership(unsigned char *ownpass, unsigned char *srkpass, keydata * key) { unsigned char take_owner_fmt[] = "00 c2 T l s @ @ % l % 00 %"; /* required OAEP padding P parameter */ unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; uint32_t ret; int iret; unsigned char tpmdata[TPM_MAX_BUFF_SIZE]; pubkeydata tpmpubkey; /* public endorsement key data */ uint32_t srkparamsize; /* SRK parameter buffer size */ unsigned char nonceeven[TPM_HASH_SIZE]; /* even nonce (from OIAPopen) */ RSA *pubkey; /* PubEK converted to OpenSSL format */ unsigned char padded[RSA_MODULUS_BYTE_SIZE]; keydata srk; /* key info for SRK */ unsigned char dummypass[TPM_HASH_SIZE]; /* dummy srk password */ unsigned char *spass; /* pointer to srkpass or dummy */ unsigned int i; /* data to be inserted into Take Owner Request Buffer */ /* the uint32_t and uint16_t values are stored in network byte order */ uint32_t command; /* command ordinal */ uint16_t protocol; /* protocol ID */ uint32_t oencdatasize; /* owner auth data encrypted size */ unsigned char ownerencr[RSA_MODULUS_BYTE_SIZE]; uint32_t sencdatasize; /* srk auth data encrypted size */ unsigned char srkencr[RSA_MODULUS_BYTE_SIZE]; unsigned char srk_param_buff[TPM_SRK_PARAM_BUFF_SIZE]; uint32_t authhandle; /* auth handle (from OIAPopen) */ unsigned char nonceodd[TPM_HASH_SIZE]; /* odd nonce */ unsigned char authdata[TPM_HASH_SIZE]; /* auth data */ /* check that parameters are valid */ if (ownpass == NULL) return ERR_NULL_ARG; if (srkpass == NULL) { memset(dummypass, 0, sizeof dummypass); spass = dummypass; } else spass = srkpass; /* set up command and protocol values for TakeOwnership function */ command = htonl(0x0d); protocol = htons(0x05); /* get the TPM Endorsement Public Key */ ret = TPM_ReadPubek(&tpmpubkey); if (ret) return ret; /* convert the public key to OpenSSL format */ pubkey = TSS_convpubkey(&tpmpubkey); if (pubkey == NULL) return ERR_CRYPT_ERR; memset(ownerencr, 0, sizeof ownerencr); memset(srkencr, 0, sizeof srkencr); /* Pad and then encrypt the owner data using the RSA public key */ iret = RSA_padding_add_PKCS1_OAEP(padded, RSA_MODULUS_BYTE_SIZE, ownpass, TPM_HASH_SIZE, tpm_oaep_pad_str, sizeof tpm_oaep_pad_str); if (iret == 0) return ERR_CRYPT_ERR; iret = RSA_public_encrypt(RSA_MODULUS_BYTE_SIZE, padded, ownerencr, pubkey, RSA_NO_PADDING); if (iret < 0) return ERR_CRYPT_ERR; oencdatasize = htonl(iret); /* Pad and then encrypt the SRK data using the RSA public key */ iret = RSA_padding_add_PKCS1_OAEP(padded, RSA_MODULUS_BYTE_SIZE, spass, TPM_HASH_SIZE, tpm_oaep_pad_str, sizeof tpm_oaep_pad_str); if (iret == 0) return ERR_CRYPT_ERR; iret = RSA_public_encrypt(RSA_MODULUS_BYTE_SIZE, padded, srkencr, pubkey, RSA_NO_PADDING); if (iret < 0) return ERR_CRYPT_ERR; sencdatasize = htonl(iret); RSA_free(pubkey); if (ntohl(oencdatasize) < 0) return ERR_CRYPT_ERR; if (ntohl(sencdatasize) < 0) return ERR_CRYPT_ERR; /* fill the SRK-params key structure */ /* get tpm version */ ret = TPM_GetCapability(0x00000006, NULL, 0, &(srk.version[0]), &i); if (ret != 0) return ret; srk.keyusage = 0x0011; /* Storage Key */ srk.keyflags = 0; if (srkpass != NULL) srk.authdatausage = 0x01; else srk.authdatausage = 0x00; srk.privkeylen = 0; /* private key not specified here */ srk.pub.algorithm = 0x00000001; /* RSA */ srk.pub.encscheme = 0x0003; /* RSA OAEP SHA1 MGF1 */ srk.pub.sigscheme = 0x0001; /* NONE */ srk.pub.keybitlen = RSA_MODULUS_BIT_SIZE; srk.pub.numprimes = 2; srk.pub.expsize = 0; /* defaults to 0x010001 */ srk.pub.keylength = 0; /* not used here */ srk.pub.pcrinfolen = 0; /* not used here */ /* convert to a memory buffer */ srkparamsize = TPM_BuildKey(srk_param_buff, &srk); /* generate the odd nonce */ ret = TSS_gennonce(nonceodd); if (ret == 0) return ret; /* initiate the OIAP protocol */ ret = TSS_OIAPopen(&authhandle, nonceeven); if (ret != 0) return ret; /* calculate the Authorization Data */ ret = TSS_authhmac(authdata, ownpass, TPM_HASH_SIZE, nonceeven, nonceodd, 0, TPM_U32_SIZE, &command, TPM_U16_SIZE, &protocol, TPM_U32_SIZE, &oencdatasize, ntohl(oencdatasize), ownerencr, TPM_U32_SIZE, &sencdatasize, ntohl(sencdatasize), srkencr, srkparamsize, srk_param_buff, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle); return ret; } /* insert all the calculated fields into the request buffer */ ret = TSS_buildbuff(take_owner_fmt, tpmdata, command, protocol, ntohl(oencdatasize), ownerencr, ntohl(sencdatasize), srkencr, srkparamsize, srk_param_buff, authhandle, TPM_HASH_SIZE, nonceodd, TPM_HASH_SIZE, authdata); if ((ret & ERR_MASK) != 0) { TSS_OIAPclose(authhandle); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "Take Ownership"); TSS_OIAPclose(authhandle); if (ret != 0) return ret; /* check the response HMAC */ srkparamsize = TSS_KeySize(tpmdata + TPM_DATA_OFFSET); ret = TSS_checkhmac1(tpmdata, command, nonceodd, ownpass, TPM_HASH_SIZE, srkparamsize, TPM_DATA_OFFSET, 0, 0); if (ret != 0) return ret; /* convert the returned key to a structure */ if (key == NULL) return 0; TSS_KeyExtract(tpmdata + TPM_DATA_OFFSET, key); return 0; }
/* XXX int set to unsigned int values */ int Trspi_RSA_Encrypt(unsigned char *dataToEncrypt, /* in */ unsigned int dataToEncryptLen, /* in */ unsigned char *encryptedData, /* out */ unsigned int *encryptedDataLen, /* out */ unsigned char *publicKey, unsigned int keysize) { int rv; unsigned char exp[] = { 0x01, 0x00, 0x01 }; /* 65537 hex */ unsigned char oaepPad[] = "TCPA"; int oaepPadLen = 4; RSA *rsa = RSA_new(); BYTE encodedData[256]; int encodedDataLen; if (rsa == NULL) { rv = TSPERR(TSS_E_OUTOFMEMORY); goto err; } /* set the public key value in the OpenSSL object */ rsa->n = BN_bin2bn(publicKey, keysize, rsa->n); /* set the public exponent */ rsa->e = BN_bin2bn(exp, sizeof(exp), rsa->e); if (rsa->n == NULL || rsa->e == NULL) { rv = TSPERR(TSS_E_OUTOFMEMORY); goto err; } /* padding constraint for PKCS#1 OAEP padding */ if ((int)dataToEncryptLen >= (RSA_size(rsa) - ((2 * SHA_DIGEST_LENGTH) + 1))) { rv = TSPERR(TSS_E_INTERNAL_ERROR); goto err; } encodedDataLen = MIN(RSA_size(rsa), 256); /* perform our OAEP padding here with custom padding parameter */ rv = RSA_padding_add_PKCS1_OAEP(encodedData, encodedDataLen, dataToEncrypt, dataToEncryptLen, oaepPad, oaepPadLen); if (rv != EVP_SUCCESS) { rv = TSPERR(TSS_E_INTERNAL_ERROR); goto err; } /* call OpenSSL with no additional padding */ rv = RSA_public_encrypt(encodedDataLen, encodedData, encryptedData, rsa, RSA_NO_PADDING); if (rv == -1) { rv = TSPERR(TSS_E_INTERNAL_ERROR); goto err; } /* RSA_public_encrypt returns the size of the encrypted data */ *encryptedDataLen = rv; rv = TSS_SUCCESS; goto out; err: DEBUG_print_openssl_errors(); out: if (rsa) RSA_free(rsa); 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 RSA_eay_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { BIGNUM f,ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; BN_init(&f); BN_init(&ret); if ((ctx=BN_CTX_new()) == NULL) goto err; num=BN_num_bytes(rsa->n); if ((buf=(unsigned char *)Malloc(num)) == NULL) { RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE); goto err; } switch (padding) { case RSA_PKCS1_PADDING: i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen); break; #ifndef _OPENSSL_APPLE_CDSA_ #ifndef NO_SHA case RSA_PKCS1_OAEP_PADDING: i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0); break; #endif #endif case RSA_SSLV23_PADDING: i=RSA_padding_add_SSLv23(buf,num,from,flen); break; case RSA_NO_PADDING: i=RSA_padding_add_none(buf,num,from,flen); break; default: RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE); goto err; } if (i <= 0) goto err; if (BN_bin2bn(buf,num,&f) == NULL) goto err; if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) { if ((rsa->_method_mod_n=BN_MONT_CTX_new()) != NULL) if (!BN_MONT_CTX_set(rsa->_method_mod_n,rsa->n,ctx)) goto err; } if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; /* put in leading 0 bytes if the number is less than the * length of the modulus */ j=BN_num_bytes(&ret); i=BN_bn2bin(&ret,&(to[num-j])); for (k=0; k<(num-i); k++) to[k]=0; r=num; err: if (ctx != NULL) BN_CTX_free(ctx); BN_clear_free(&f); BN_clear_free(&ret); if (buf != NULL) { memset(buf,0,num); Free(buf); } return(r); }
static int xmlSecOpenSSLRsaOaepProcess(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) { xmlSecOpenSSLRsaOaepCtxPtr ctx; xmlSecSize paramsSize; xmlSecBufferPtr in, out; xmlSecSize inSize, outSize; xmlSecSize keySize; int ret; xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); xmlSecAssert2(transformCtx != NULL, -1); ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->pKey != NULL, -1); xmlSecAssert2(ctx->pKey->type == EVP_PKEY_RSA, -1); xmlSecAssert2(ctx->pKey->pkey.rsa != NULL, -1); keySize = RSA_size(ctx->pKey->pkey.rsa); xmlSecAssert2(keySize > 0, -1); in = &(transform->inBuf); out = &(transform->outBuf); inSize = xmlSecBufferGetSize(in); outSize = xmlSecBufferGetSize(out); xmlSecAssert2(outSize == 0, -1); /* the encoded size is equal to the keys size so we could not * process more than that */ if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), NULL, XMLSEC_ERRORS_R_INVALID_SIZE, "%d when expected less than %d", inSize, keySize); return(-1); } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), NULL, XMLSEC_ERRORS_R_INVALID_SIZE, "%d when expected %d", inSize, keySize); return(-1); } outSize = keySize; ret = xmlSecBufferSetMaxSize(out, outSize); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecBufferSetMaxSize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", outSize); return(-1); } paramsSize = xmlSecBufferGetSize(&(ctx->oaepParams)); if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize == 0)) { /* encode w/o OAEPParams --> simple */ ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING); if(ret <= 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "RSA_public_encrypt(RSA_PKCS1_OAEP_PADDING)", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } outSize = ret; } else if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize > 0)) { xmlSecAssert2(xmlSecBufferGetData(&(ctx->oaepParams)) != NULL, -1); /* add space for padding */ ret = xmlSecBufferSetMaxSize(in, keySize); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecBufferSetMaxSize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", keySize); return(-1); } /* add padding */ ret = RSA_padding_add_PKCS1_OAEP(xmlSecBufferGetData(in), keySize, xmlSecBufferGetData(in), inSize, xmlSecBufferGetData(&(ctx->oaepParams)), paramsSize); if(ret != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "RSA_padding_add_PKCS1_OAEP", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } inSize = keySize; /* encode with OAEPParams */ ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), ctx->pKey->pkey.rsa, RSA_NO_PADDING); if(ret <= 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "RSA_public_encrypt(RSA_NO_PADDING)", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } outSize = ret; } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize == 0)) { ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), ctx->pKey->pkey.rsa, RSA_PKCS1_OAEP_PADDING); if(ret <= 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "RSA_private_decrypt(RSA_PKCS1_OAEP_PADDING)", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } outSize = ret; } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize != 0)) { BIGNUM bn; ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), ctx->pKey->pkey.rsa, RSA_NO_PADDING); if(ret <= 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "RSA_private_decrypt(RSA_NO_PADDING)", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } outSize = ret; /* * the private decrypt w/o padding adds '0's at the begginning. * it's not clear for me can I simply skip all '0's from the * beggining so I have to do decode it back to BIGNUM and dump * buffer again */ BN_init(&bn); if(BN_bin2bn(xmlSecBufferGetData(out), outSize, &bn) == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "BN_bin2bn", XMLSEC_ERRORS_R_CRYPTO_FAILED, "size=%d", outSize); BN_clear_free(&bn); return(-1); } ret = BN_bn2bin(&bn, xmlSecBufferGetData(out)); if(ret <= 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "BN_bn2bin", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); BN_clear_free(&bn); return(-1); } BN_clear_free(&bn); outSize = ret; ret = RSA_padding_check_PKCS1_OAEP(xmlSecBufferGetData(out), outSize, xmlSecBufferGetData(out), outSize, keySize, xmlSecBufferGetData(&(ctx->oaepParams)), paramsSize); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "RSA_padding_check_PKCS1_OAEP", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } outSize = ret; } else { xmlSecAssert2("we could not be here" == NULL, -1); return(-1); } ret = xmlSecBufferSetSize(out, outSize); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecBufferSetSize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", outSize); return(-1); } ret = xmlSecBufferRemoveHead(in, inSize); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecBufferRemoveHead", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", inSize); return(-1); } return(0); }
static int xmlSecOpenSSLRsaOaepProcess(xmlSecTransformPtr transform, xmlSecTransformCtxPtr transformCtx) { xmlSecOpenSSLRsaOaepCtxPtr ctx; xmlSecSize paramsSize; xmlSecBufferPtr in, out; xmlSecSize inSize, outSize; xmlSecSize keySize; RSA *rsa; int ret; xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformRsaOaepId), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLRsaOaepSize), -1); xmlSecAssert2(transformCtx != NULL, -1); ctx = xmlSecOpenSSLRsaOaepGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->pKey != NULL, -1); xmlSecAssert2(EVP_PKEY_base_id(ctx->pKey) == EVP_PKEY_RSA, -1); rsa = EVP_PKEY_get0_RSA(ctx->pKey); xmlSecAssert2(rsa != NULL, -1); keySize = RSA_size(rsa); xmlSecAssert2(keySize > 0, -1); in = &(transform->inBuf); out = &(transform->outBuf); inSize = xmlSecBufferGetSize(in); outSize = xmlSecBufferGetSize(out); xmlSecAssert2(outSize == 0, -1); /* the encoded size is equal to the keys size so we could not * process more than that */ if((transform->operation == xmlSecTransformOperationEncrypt) && (inSize >= keySize)) { xmlSecInvalidSizeLessThanError("Input data", inSize, keySize, xmlSecTransformGetName(transform)); return(-1); } else if((transform->operation == xmlSecTransformOperationDecrypt) && (inSize != keySize)) { xmlSecInvalidSizeError("Input data", inSize, keySize, xmlSecTransformGetName(transform)); return(-1); } outSize = keySize; ret = xmlSecBufferSetMaxSize(out, outSize); if(ret < 0) { xmlSecInternalError2("xmlSecBufferSetMaxSize", xmlSecTransformGetName(transform), "size=%d", outSize); return(-1); } paramsSize = xmlSecBufferGetSize(&(ctx->oaepParams)); if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize == 0)) { /* encode w/o OAEPParams --> simple */ ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), rsa, RSA_PKCS1_OAEP_PADDING); if(ret <= 0) { xmlSecOpenSSLError("RSA_public_encrypt(RSA_PKCS1_OAEP_PADDING)", xmlSecTransformGetName(transform)); return(-1); } outSize = ret; } else if((transform->operation == xmlSecTransformOperationEncrypt) && (paramsSize > 0)) { xmlSecAssert2(xmlSecBufferGetData(&(ctx->oaepParams)) != NULL, -1); /* add space for padding */ ret = xmlSecBufferSetMaxSize(in, keySize); if(ret < 0) { xmlSecInternalError2("xmlSecBufferSetMaxSize", xmlSecTransformGetName(transform), "size=%d", keySize); return(-1); } /* add padding */ ret = RSA_padding_add_PKCS1_OAEP(xmlSecBufferGetData(in), keySize, xmlSecBufferGetData(in), inSize, xmlSecBufferGetData(&(ctx->oaepParams)), paramsSize); if(ret != 1) { xmlSecOpenSSLError("RSA_padding_add_PKCS1_OAEP", xmlSecTransformGetName(transform)); return(-1); } inSize = keySize; /* encode with OAEPParams */ ret = RSA_public_encrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), rsa, RSA_NO_PADDING); if(ret <= 0) { xmlSecOpenSSLError("RSA_public_encrypt(RSA_NO_PADDING)", xmlSecTransformGetName(transform)); return(-1); } outSize = ret; } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize == 0)) { ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), rsa, RSA_PKCS1_OAEP_PADDING); if(ret <= 0) { xmlSecOpenSSLError("RSA_private_decrypt(RSA_PKCS1_OAEP_PADDING)", xmlSecTransformGetName(transform)); return(-1); } outSize = ret; } else if((transform->operation == xmlSecTransformOperationDecrypt) && (paramsSize != 0)) { BIGNUM * bn; bn = BN_new(); if(bn == NULL) { xmlSecOpenSSLError("BN_new()", xmlSecTransformGetName(transform)); return(-1); } ret = RSA_private_decrypt(inSize, xmlSecBufferGetData(in), xmlSecBufferGetData(out), rsa, RSA_NO_PADDING); if(ret <= 0) { xmlSecOpenSSLError("RSA_private_decrypt(RSA_NO_PADDING)", xmlSecTransformGetName(transform)); BN_free(bn); return(-1); } outSize = ret; /* * the private decrypt w/o padding adds '0's at the begginning. * it's not clear for me can I simply skip all '0's from the * beggining so I have to do decode it back to BIGNUM and dump * buffer again */ if(BN_bin2bn(xmlSecBufferGetData(out), outSize, bn) == NULL) { xmlSecOpenSSLError2("BN_bin2bn", xmlSecTransformGetName(transform), "size=%lu", (unsigned long)outSize); BN_free(bn); return(-1); } ret = BN_bn2bin(bn, xmlSecBufferGetData(out)); if(ret <= 0) { xmlSecOpenSSLError("BN_bn2bin", xmlSecTransformGetName(transform)); BN_free(bn); return(-1); } BN_free(bn); outSize = ret; ret = RSA_padding_check_PKCS1_OAEP(xmlSecBufferGetData(out), outSize, xmlSecBufferGetData(out), outSize, keySize, xmlSecBufferGetData(&(ctx->oaepParams)), paramsSize); if(ret < 0) { xmlSecOpenSSLError("RSA_padding_check_PKCS1_OAEP", xmlSecTransformGetName(transform)); return(-1); } outSize = ret; } else { xmlSecOtherError3(XMLSEC_ERRORS_R_INVALID_OPERATION, xmlSecTransformGetName(transform), "Unexpected transform operation: %ld; paramsSize: %ld", (long int)transform->operation, (long int)paramsSize); return(-1); } ret = xmlSecBufferSetSize(out, outSize); if(ret < 0) { xmlSecInternalError2("xmlSecBufferSetSize", xmlSecTransformGetName(transform), "size=%d", outSize); return(-1); } ret = xmlSecBufferRemoveHead(in, inSize); if(ret < 0) { xmlSecInternalError2("xmlSecBufferRemoveHead", xmlSecTransformGetName(transform), "size=%d", inSize); return(-1); } return(0); }