Home | History | Annotate | Line # | Download | only in openssl
      1 
      2 /*
      3  * Licensed Materials - Property of IBM
      4  *
      5  * trousers - An open source TCG Software Stack
      6  *
      7  * (C) Copyright International Business Machines Corp. 2004-2006
      8  *
      9  */
     10 
     11 /*
     12  * rsa.c - openssl TSS crypto routines
     13  *
     14  * Kent Yoder <shpedoikal (at) gmail.com>
     15  *
     16  */
     17 
     18 #include <string.h>
     19 
     20 #include <openssl/evp.h>
     21 #include <openssl/err.h>
     22 #include <openssl/sha.h>
     23 #include <openssl/rsa.h>
     24 
     25 #include "trousers/tss.h"
     26 #include "trousers/trousers.h"
     27 #include "trousers_types.h"
     28 #include "spi_utils.h"
     29 #include "tsplog.h"
     30 
     31 #ifdef TSS_DEBUG
     32 #define DEBUG_print_openssl_errors() \
     33 	do { \
     34 		ERR_load_crypto_strings(); \
     35 		ERR_print_errors_fp(stderr); \
     36 	} while (0)
     37 #else
     38 #define DEBUG_print_openssl_errors()
     39 #endif
     40 
     41 #if OPENSSL_VERSION_NUMBER < 0x10100001L
     42 static int
     43 RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
     44 {
     45 	if (n != NULL) {
     46 		BN_free(r->n);
     47 		r->n = n;
     48 	}
     49 	if (e != NULL) {
     50 		BN_free(r->e);
     51 		r->e = e;
     52 	}
     53 	if (d != NULL) {
     54 		BN_free(r->d);
     55 		r->d = d;
     56 	}
     57 	return 1;
     58 }
     59 #endif
     60 
     61 /*
     62  * Hopefully this will make the code clearer since
     63  * OpenSSL returns 1 on success
     64  */
     65 #define EVP_SUCCESS 1
     66 
     67 /* XXX int set to unsigned int values */
     68 int
     69 Trspi_RSA_Encrypt(unsigned char *dataToEncrypt, /* in */
     70 		unsigned int dataToEncryptLen,  /* in */
     71 		unsigned char *encryptedData,   /* out */
     72 		unsigned int *encryptedDataLen, /* out */
     73 		unsigned char *publicKey,
     74 		unsigned int keysize)
     75 {
     76 	int rv;
     77 	unsigned char exp[] = { 0x01, 0x00, 0x01 }; /* 65537 hex */
     78 	unsigned char oaepPad[] = "TCPA";
     79 	int oaepPadLen = 4;
     80 	RSA *rsa = RSA_new();
     81 	BYTE encodedData[256];
     82 	int encodedDataLen;
     83 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
     84 
     85 	if (rsa == NULL) {
     86 		rv = TSPERR(TSS_E_OUTOFMEMORY);
     87 		goto err;
     88 	}
     89 
     90 	/* set the public key value in the OpenSSL object */
     91 	rsa_n = BN_bin2bn(publicKey, keysize, NULL);
     92 	/* set the public exponent */
     93 	rsa_e = BN_bin2bn(exp, sizeof(exp), NULL);
     94 
     95 	if (rsa_n == NULL || rsa_e == NULL) {
     96 		rv = TSPERR(TSS_E_OUTOFMEMORY);
     97 		BN_free(rsa_n);
     98 		BN_free(rsa_e);
     99 		goto err;
    100 	}
    101 	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
    102 		rv = TSPERR(TSS_E_FAIL);
    103 		BN_free(rsa_n);
    104 		BN_free(rsa_e);
    105 		goto err;
    106 	}
    107 
    108 	/* padding constraint for PKCS#1 OAEP padding */
    109 	if ((int)dataToEncryptLen >= (RSA_size(rsa) - ((2 * SHA_DIGEST_LENGTH) + 1))) {
    110 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
    111 		goto err;
    112 	}
    113 
    114 	encodedDataLen = MIN(RSA_size(rsa), 256);
    115 
    116 	/* perform our OAEP padding here with custom padding parameter */
    117 	rv = RSA_padding_add_PKCS1_OAEP(encodedData, encodedDataLen, dataToEncrypt,
    118 			dataToEncryptLen, oaepPad, oaepPadLen);
    119 	if (rv != EVP_SUCCESS) {
    120 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
    121 		goto err;
    122 	}
    123 
    124 	/* call OpenSSL with no additional padding */
    125 	rv = RSA_public_encrypt(encodedDataLen, encodedData,
    126 				encryptedData, rsa, RSA_NO_PADDING);
    127 	if (rv == -1) {
    128 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
    129 		goto err;
    130 	}
    131 
    132 	/* RSA_public_encrypt returns the size of the encrypted data */
    133 	*encryptedDataLen = rv;
    134 	rv = TSS_SUCCESS;
    135 	goto out;
    136 
    137 err:
    138 	DEBUG_print_openssl_errors();
    139 out:
    140 	if (rsa)
    141 		RSA_free(rsa);
    142         return rv;
    143 }
    144 
    145 TSS_RESULT
    146 Trspi_Verify(UINT32 HashType, BYTE *pHash, UINT32 iHashLength,
    147 	     unsigned char *pModulus, int iKeyLength,
    148 	     BYTE *pSignature, UINT32 sig_len)
    149 {
    150 	int rv, nid;
    151 	unsigned char exp[] = { 0x01, 0x00, 0x01 }; /* The default public exponent for the TPM */
    152 	unsigned char buf[256];
    153 	RSA *rsa = RSA_new();
    154 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
    155 
    156 	if (rsa == NULL) {
    157 		rv = TSPERR(TSS_E_OUTOFMEMORY);
    158 		goto err;
    159 	}
    160 
    161 	/* We assume we're verifying data from a TPM, so there are only
    162 	 * two options, SHA1 data and PKCSv1.5 encoded signature data.
    163 	 */
    164 	switch (HashType) {
    165 		case TSS_HASH_SHA1:
    166 			nid = NID_sha1;
    167 			break;
    168 		case TSS_HASH_OTHER:
    169 			nid = NID_undef;
    170 			break;
    171 		default:
    172 			rv = TSPERR(TSS_E_BAD_PARAMETER);
    173 			goto out;
    174 			break;
    175 	}
    176 
    177 	/* set the public key value in the OpenSSL object */
    178 	rsa_n = BN_bin2bn(pModulus, iKeyLength, NULL);
    179 	/* set the public exponent */
    180 	rsa_e = BN_bin2bn(exp, sizeof(exp), NULL);
    181 
    182 	if (rsa_n == NULL || rsa_e == NULL) {
    183 		rv = TSPERR(TSS_E_OUTOFMEMORY);
    184 		BN_free(rsa_n);
    185 		BN_free(rsa_e);
    186 		goto err;
    187 	}
    188 	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
    189 		rv = TSPERR(TSS_E_FAIL);
    190 		BN_free(rsa_n);
    191 		BN_free(rsa_e);
    192 		goto err;
    193 	}
    194 
    195 	/* if we don't know the structure of the data we're verifying, do a public decrypt
    196 	 * and compare manually. If we know we're looking for a SHA1 hash, allow OpenSSL
    197 	 * to do the work for us.
    198 	 */
    199 	if (nid == NID_undef) {
    200 		rv = RSA_public_decrypt(sig_len, pSignature, buf, rsa, RSA_PKCS1_PADDING);
    201 		if ((UINT32)rv != iHashLength) {
    202 			rv = TSPERR(TSS_E_FAIL);
    203 			goto out;
    204 		} else if (memcmp(pHash, buf, iHashLength)) {
    205 			rv = TSPERR(TSS_E_FAIL);
    206 			goto out;
    207 		}
    208 	} else {
    209 		if ((rv = RSA_verify(nid, pHash, iHashLength, pSignature, sig_len, rsa)) == 0) {
    210 			rv = TSPERR(TSS_E_FAIL);
    211 			goto out;
    212 		}
    213 	}
    214 
    215 	rv = TSS_SUCCESS;
    216 	goto out;
    217 
    218 err:
    219 	DEBUG_print_openssl_errors();
    220 out:
    221 	if (rsa)
    222 		RSA_free(rsa);
    223         return rv;
    224 }
    225 
    226 int
    227 Trspi_RSA_Public_Encrypt(unsigned char *in, unsigned int inlen,
    228 			 unsigned char *out, unsigned int *outlen,
    229 			 unsigned char *pubkey, unsigned int pubsize,
    230 			 unsigned int e, int padding)
    231 {
    232 	int rv, e_size = 3;
    233 	unsigned char exp[] = { 0x01, 0x00, 0x01 };
    234 	RSA *rsa = RSA_new();
    235 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
    236 
    237 	if (rsa == NULL) {
    238 		rv = TSPERR(TSS_E_OUTOFMEMORY);
    239 		goto err;
    240 	}
    241 
    242 	switch (e) {
    243 		case 0:
    244 			/* fall through */
    245 		case 65537:
    246 			break;
    247 		case 17:
    248 			exp[0] = 17;
    249 			e_size = 1;
    250 			break;
    251 		case 3:
    252 			exp[0] = 3;
    253 			e_size = 1;
    254 			break;
    255 		default:
    256 			rv = TSPERR(TSS_E_INTERNAL_ERROR);
    257 			goto out;
    258 			break;
    259 	}
    260 
    261 	switch (padding) {
    262 		case TR_RSA_PKCS1_OAEP_PADDING:
    263 			padding = RSA_PKCS1_OAEP_PADDING;
    264 			break;
    265 		case TR_RSA_PKCS1_PADDING:
    266 			padding = RSA_PKCS1_PADDING;
    267 			break;
    268 		case TR_RSA_NO_PADDING:
    269 			padding = RSA_NO_PADDING;
    270 			break;
    271 		default:
    272 			rv = TSPERR(TSS_E_INTERNAL_ERROR);
    273 			goto out;
    274 			break;
    275 	}
    276 
    277 	/* set the public key value in the OpenSSL object */
    278 	rsa_n = BN_bin2bn(pubkey, pubsize, NULL);
    279 	/* set the public exponent */
    280 	rsa_e = BN_bin2bn(exp, e_size, NULL);
    281 
    282 	if (rsa_n == NULL || rsa_e == NULL) {
    283 		rv = TSPERR(TSS_E_OUTOFMEMORY);
    284                 BN_free(rsa_n);
    285                 BN_free(rsa_e);
    286                 goto err;
    287         }
    288         if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
    289                 rv = TSPERR(TSS_E_FAIL);
    290                 BN_free(rsa_n);
    291                 BN_free(rsa_e);
    292 		goto err;
    293 	}
    294 
    295 	rv = RSA_public_encrypt(inlen, in, out, rsa, padding);
    296 	if (rv == -1) {
    297 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
    298 		goto err;
    299 	}
    300 
    301 	/* RSA_public_encrypt returns the size of the encrypted data */
    302 	*outlen = rv;
    303 	rv = TSS_SUCCESS;
    304 	goto out;
    305 
    306 err:
    307 	DEBUG_print_openssl_errors();
    308 out:
    309 	if (rsa)
    310 		RSA_free(rsa);
    311         return rv;
    312 }
    313