ia64/xen-unstable

view tools/vtpm_manager/crypto/rsa.c @ 8977:f84d5cdd9895

Clean up segment selector fixup and validation.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 23 14:43:45 2006 +0100 (2006-02-23)
parents 06d84bf87159
children
line source
1 // ===================================================================
2 //
3 // Copyright (c) 2005, Intel Corp.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 // * Neither the name of Intel Corporation nor the names of its
17 // contributors may be used to endorse or promote products derived
18 // from this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32 // ===================================================================
33 //
34 // rsa.c
35 //
36 // This file will handle all the TPM RSA crypto functionality
37 //
38 // ==================================================================
40 #include <string.h>
41 #include <openssl/crypto.h>
42 #include <openssl/evp.h>
43 #include <openssl/bn.h>
44 #include <openssl/rsa.h>
45 #include <openssl/rand.h>
46 #include <openssl/x509.h>
48 #include <openssl/err.h>
49 #include <stdio.h>
51 #include "tcg.h"
52 #include "buffer.h"
53 #include "crypto.h"
54 #include "log.h"
56 void Crypto_RSACreateKey( /*in*/ UINT32 keySize,
57 /*in*/ UINT32 pubExpSize,
58 /*in*/ BYTE *pubExp,
59 /*out*/ UINT32 *privExpSize,
60 /*out*/ BYTE *privExp,
61 /*out*/ UINT32 *modulusSize,
62 /*out*/ BYTE *modulus,
63 /*out*/ CRYPTO_INFO *keys) {
64 unsigned long e_value;
66 if (pubExpSize == 0) // Default e = 2^16+1
67 e_value = (0x01 << 16) + 1;
68 else {
69 // This is not supported, but the following line MIGHT work
70 // under then assumption that the format is BigNum compatable
71 // Though it's not in the spec, so who knows what it is.
72 // Forcing the default.
73 //BN_bin2bn(pubExp, pubExpSize, NULL);
74 e_value = (0x01 << 16) + 1;
75 }
77 RSA *rsa = RSA_generate_key(keySize, e_value, NULL, NULL);
79 if (keys) {
80 keys->keyInfo = rsa;
81 keys->algorithmID = CRYPTO_ALGORITH_RSA;
82 }
84 if (modulus) *modulusSize = BN_bn2bin(rsa->n, modulus);
85 if (privExp) *privExpSize = BN_bn2bin(rsa->d, privExp);
86 }
88 // Create a CRYPTO_INFO struct from the BYTE * key parts.
89 // If pubExp info is NULL, use TCG default.
90 // If there is a remainder while calculating the privExp, return FALSE.
92 void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize,
93 /*[IN]*/ BYTE *pubExp,
94 /*[IN]*/ UINT32 privExpSize,
95 /*[IN]*/ BYTE *privExp,
96 /*[IN]*/ UINT32 modulusSize,
97 /*[IN]*/ BYTE *modulus,
98 CRYPTO_INFO* cryptoInfo) {
99 cryptoInfo->keyInfo = RSA_new();
100 RSA *rsa = (RSA *) cryptoInfo->keyInfo;
102 rsa->e = BN_new();
104 if (pubExpSize == 0) { // Default e = 2^16+1
105 BN_set_bit(rsa->e, 16);
106 BN_set_bit(rsa->e, 0);
107 } else {
108 // This is not supported, but the following line MIGHT work
109 // under then assumption that the format is BigNum compatable
110 // Though it's not in the spec, so who knows what it is.
111 // Forcing the default.
112 //BN_bin2bn(pubExp, pubExpSize, NULL);
113 BN_set_bit(rsa->e, 16);
114 BN_set_bit(rsa->e, 0);
115 }
117 rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
118 rsa->d = BN_bin2bn(privExp, privExpSize, NULL);
119 }
121 // Create a CRYPTO_INFO struct from the BYTE * key parts.
122 // If pubExp info is NULL, use TCG default.
123 // If there is a remainder while calculating the privExp, return FALSE.
125 void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize,
126 /*[IN]*/ BYTE *pubExp,
127 /*[IN]*/ UINT32 modulusSize,
128 /*[IN]*/ BYTE *modulus,
129 CRYPTO_INFO* cryptoInfo) {
130 cryptoInfo->keyInfo = RSA_new();
131 RSA *rsa = (RSA *) cryptoInfo->keyInfo;
133 rsa->e = BN_new();
135 if (pubExpSize == 0) { // Default e = 2^16+1
136 BN_set_bit(rsa->e, 16);
137 BN_set_bit(rsa->e, 0);
138 } else {
139 // This is not supported, but the following line MIGHT work
140 // under then assumption that the format is BigNum compatable
141 // Though it's not in the spec, so who knows what it is.
142 // Forcing the default.
143 //BN_bin2bn(pubExp, pubExpSize, NULL);
144 BN_set_bit(rsa->e, 16);
145 BN_set_bit(rsa->e, 0);
146 }
148 rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
150 }
152 int Crypto_RSAEnc( CRYPTO_INFO *key,
153 UINT32 inDataSize,
154 BYTE *inData,
155 /*out*/ UINT32 *outDataSize,
156 /*out*/ BYTE *outData) {
157 RSA *rsa = (RSA *) key->keyInfo;
158 UINT32 paddedDataSize = RSA_size (rsa);
159 BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
160 int rc;
162 if (paddedData == NULL)
163 return -1;
165 *outDataSize = 0;
167 switch (key->encScheme) {
168 case CRYPTO_ES_RSAESPKCSv15:
169 if (RSA_padding_add_PKCS1_type_2(paddedData, paddedDataSize, inData, inDataSize) <= 0) {
170 rc = -1;
171 goto abort_egress;
172 }
173 break;
174 case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
175 if (RSA_padding_add_PKCS1_OAEP(paddedData,paddedDataSize,inData,inDataSize, (BYTE *) OAEP_P,OAEP_P_SIZE) <= 0 ) {
176 rc = -1;
177 goto abort_egress;
178 }
179 break;
180 default:
181 rc = -1;
182 goto abort_egress;
183 }
185 rc = RSA_public_encrypt(paddedDataSize, paddedData, outData, rsa, RSA_NO_PADDING);
186 if (rc == -1)
187 goto abort_egress;
189 *outDataSize = rc;
191 if (rc > 0) rc = 0;
193 goto egress;
195 abort_egress:
196 egress:
198 if (paddedData)
199 free (paddedData);
200 return rc;
202 }
204 int Crypto_RSADec( CRYPTO_INFO *key,
205 UINT32 inDataSize,
206 BYTE *inData,
207 /*out*/ UINT32 *outDataSize,
208 /*out*/ BYTE *outData) {
210 RSA *rsa = (RSA *) key->keyInfo;
211 UINT32 paddedDataSize = RSA_size (rsa);
212 BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
213 int rc;
215 if (paddedData == NULL)
216 goto abort_egress;
218 rc = RSA_private_decrypt(inDataSize, inData, paddedData, rsa, RSA_NO_PADDING);
219 if (rc == -1) {
220 vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_private_decrypt: %s\n", ERR_error_string(ERR_get_error(), NULL));
221 goto abort_egress;
222 }
224 paddedDataSize = rc;
226 switch (key->encScheme) {
227 case CRYPTO_ES_RSAESPKCSv15:
228 rc = RSA_padding_check_PKCS1_type_2 (outData, paddedDataSize,
229 paddedData + 1, paddedDataSize - 1,
230 RSA_size(rsa));
231 if (rc == -1) {
232 vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_type_2: %s\n",
233 ERR_error_string(ERR_get_error(), NULL));
234 goto abort_egress;
235 }
236 *outDataSize = rc;
237 break;
238 case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
239 rc = RSA_padding_check_PKCS1_OAEP(outData, paddedDataSize,
240 paddedData + 1, paddedDataSize - 1,
241 RSA_size(rsa),
242 (BYTE *) OAEP_P, OAEP_P_SIZE);
243 if (rc == -1) {
244 vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_OAEP: %s\n",
245 ERR_error_string(ERR_get_error(), NULL));
246 goto abort_egress;
247 }
248 *outDataSize = rc;
249 break;
250 default:
251 *outDataSize = 0;
252 }
254 free(paddedData); paddedData = NULL;
255 goto egress;
257 abort_egress:
259 if (paddedData)
260 free (paddedData);
261 return -1;
263 egress:
264 return 0;
265 }
267 // Signs either a SHA1 digest of a message or a DER encoding of a message
268 // Textual messages MUST be encoded or Hashed before sending into this function
269 // It will NOT SHA the message.
270 int Crypto_RSASign( CRYPTO_INFO *key,
271 UINT32 inDataSize,
272 BYTE *inData,
273 /*out*/ UINT32 *sigSize,
274 /*out*/ BYTE *sig) {
275 int status;
276 unsigned int intSigSize;
278 switch(key->sigScheme) {
279 case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
280 status = RSA_sign(NID_sha1, inData, inDataSize, sig, &intSigSize, (RSA *) key->keyInfo);
281 break;
282 case CRYPTO_SS_RSASSAPKCS1v15_DER:
283 // status = Crypto_RSA_sign_DER(NID_md5_sha1, inData, inDataSize, sig, &intSigSize, key);
284 vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n", key->sigScheme);
285 status = 0;
286 break;
287 default:
288 status = 0;
289 }
291 if (status == 0) {
292 *sigSize = 0;
293 vtpmlogerror(VTPM_LOG_CRYPTO, "%s\n", ERR_error_string(ERR_get_error(), NULL));
294 return -1;
295 }
297 *sigSize = (UINT32) intSigSize;
298 return 0;
299 }
301 bool Crypto_RSAVerify( CRYPTO_INFO *key,
302 UINT32 inDataSize,
303 BYTE *inData,
304 UINT32 sigSize,
305 BYTE *sig) {
306 int status;
308 switch(key->sigScheme){
309 case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
310 status = RSA_verify(NID_sha1, inData, inDataSize, sig, sigSize, (RSA *) key->keyInfo);
311 break;
312 case CRYPTO_SS_RSASSAPKCS1v15_DER:
313 //status = Crypto_RSA_verify_DER(NID_md5_sha1, inData, inDataSize, sig, sigSize, key);
314 vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n", key->sigScheme);
315 status = 0;
316 break;
317 default:
318 status = 0;
319 }
321 if (status)
322 return(1);
323 else {
324 vtpmlogerror(VTPM_LOG_CRYPTO, "RSA verify: %s\n", ERR_error_string(ERR_get_error(), NULL));
325 return(0);
326 }
328 }
330 // helper which packs everything into a BIO!
332 // packs the parameters first, then the private key, then the public key
333 // if *io_buf is NULL, allocate it here as needed. otherwise its size is in
334 // *io_buflen
335 TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
336 BYTE ** io_buf, UINT32 * io_buflen) {
337 TPM_RESULT status = TPM_SUCCESS;
338 BYTE * buf;
339 long len, outlen = *io_buflen;
341 const long PARAMSLEN = 3*sizeof(UINT32);
343 RSA *rsa = (RSA *) cryptoInfo->keyInfo;
345 BIO *mem = BIO_new(BIO_s_mem());
348 // write the openssl keys to the BIO
349 if ( i2d_RSAPrivateKey_bio (mem, rsa) == 0 ) {
350 ERR_print_errors_fp (stderr);
351 ERRORDIE (TPM_SIZE);
352 }
353 if ( i2d_RSAPublicKey_bio (mem, rsa) == 0 ) {
354 ERR_print_errors_fp (stderr);
355 ERRORDIE (TPM_SIZE);
356 }
358 // get the buffer out
359 len = BIO_get_mem_data (mem, &buf);
361 // see if we need to allocate a return buffer
362 if (*io_buf == NULL) {
363 *io_buf = (BYTE*) malloc (PARAMSLEN + len);
364 if (*io_buf == NULL)
365 ERRORDIE (TPM_SIZE);
366 } else { // *io_buf is already allocated
367 if (outlen < len + PARAMSLEN)
368 ERRORDIE (TPM_SIZE); // but not large enough!
369 }
371 // copy over the parameters (three UINT32's starting at algorithmID)
372 memcpy (*io_buf, &cryptoInfo->algorithmID, PARAMSLEN);
374 // copy over the DER keys
375 memcpy (*io_buf + PARAMSLEN, buf, len);
377 *io_buflen = len + PARAMSLEN;
379 goto egress;
382 abort_egress:
383 egress:
385 BIO_free (mem);
387 return status;
388 }
392 // sets up ci, and returns the number of bytes read in o_lenread
393 TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
394 BYTE * in, UINT32 len,
395 UINT32 * o_lenread) {
397 TPM_RESULT status = TPM_SUCCESS;
398 long l;
399 BIO *mem;
400 RSA *rsa;
402 // first load up the params
403 l = 3 * sizeof(UINT32);
404 memcpy (&ci->algorithmID, in, l);
405 len -= l;
406 in += l;
408 // and now the openssl keys, private first
409 mem = BIO_new_mem_buf (in, len);
411 if ( (rsa = d2i_RSAPrivateKey_bio (mem, NULL)) == NULL ) {
412 ERR_print_errors_fp (stderr);
413 ERRORDIE (TPM_BAD_PARAMETER);
414 }
415 // now use the same RSA object and fill in the private key
416 if ( d2i_RSAPublicKey_bio (mem, &rsa) == NULL ) {
417 ERR_print_errors_fp (stderr);
418 ERRORDIE (TPM_BAD_PARAMETER);
419 }
421 ci->keyInfo = rsa; // needs to be freed somehow later
423 // FIXME: havent figured out yet how to tell how many bytes were read in the
424 // above oprations! so o_lenread is not set
426 goto egress;
428 abort_egress:
429 egress:
431 BIO_free (mem);
433 return status;
434 }