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@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 42static int 43RSA_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 */ 68int 69Trspi_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 137err: 138 DEBUG_print_openssl_errors(); 139out: 140 if (rsa) 141 RSA_free(rsa); 142 return rv; 143} 144 145TSS_RESULT 146Trspi_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 218err: 219 DEBUG_print_openssl_errors(); 220out: 221 if (rsa) 222 RSA_free(rsa); 223 return rv; 224} 225 226int 227Trspi_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 306err: 307 DEBUG_print_openssl_errors(); 308out: 309 if (rsa) 310 RSA_free(rsa); 311 return rv; 312} 313