Annotation of embedaddon/axTLS/crypto/rsa.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2007, Cameron Rich
                      3:  * 
                      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 are met:
                      8:  *
                      9:  * * Redistributions of source code must retain the above copyright notice, 
                     10:  *   this list of conditions and the following disclaimer.
                     11:  * * Redistributions in binary form must reproduce the above copyright notice, 
                     12:  *   this list of conditions and the following disclaimer in the documentation 
                     13:  *   and/or other materials provided with the distribution.
                     14:  * * Neither the name of the axTLS project nor the names of its contributors 
                     15:  *   may be used to endorse or promote products derived from this software 
                     16:  *   without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
                     19:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
                     21:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                     22:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     23:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     24:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                     25:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
                     26:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                     27:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                     28:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30: 
                     31: /**
                     32:  * Implements the RSA public encryption algorithm. Uses the bigint library to
                     33:  * perform its calculations.
                     34:  */
                     35: 
                     36: #include <stdio.h>
                     37: #include <string.h>
                     38: #include <time.h>
                     39: #include <stdlib.h>
                     40: #include "os_port.h"
                     41: #include "crypto.h"
                     42: 
                     43: void RSA_priv_key_new(RSA_CTX **ctx, 
                     44:         const uint8_t *modulus, int mod_len,
                     45:         const uint8_t *pub_exp, int pub_len,
                     46:         const uint8_t *priv_exp, int priv_len
                     47: #if CONFIG_BIGINT_CRT
                     48:       , const uint8_t *p, int p_len,
                     49:         const uint8_t *q, int q_len,
                     50:         const uint8_t *dP, int dP_len,
                     51:         const uint8_t *dQ, int dQ_len,
                     52:         const uint8_t *qInv, int qInv_len
                     53: #endif
                     54:     )
                     55: {
                     56:     RSA_CTX *rsa_ctx;
                     57:     BI_CTX *bi_ctx;
                     58:     RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len);
                     59:     rsa_ctx = *ctx;
                     60:     bi_ctx = rsa_ctx->bi_ctx;
                     61:     rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len);
                     62:     bi_permanent(rsa_ctx->d);
                     63: 
                     64: #ifdef CONFIG_BIGINT_CRT
                     65:     rsa_ctx->p = bi_import(bi_ctx, p, p_len);
                     66:     rsa_ctx->q = bi_import(bi_ctx, q, q_len);
                     67:     rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len);
                     68:     rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len);
                     69:     rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len);
                     70:     bi_permanent(rsa_ctx->dP);
                     71:     bi_permanent(rsa_ctx->dQ);
                     72:     bi_permanent(rsa_ctx->qInv);
                     73:     bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET);
                     74:     bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET);
                     75: #endif
                     76: }
                     77: 
                     78: void RSA_pub_key_new(RSA_CTX **ctx, 
                     79:         const uint8_t *modulus, int mod_len,
                     80:         const uint8_t *pub_exp, int pub_len)
                     81: {
                     82:     RSA_CTX *rsa_ctx;
                     83:     BI_CTX *bi_ctx;
                     84: 
                     85:     if (*ctx)   /* if we load multiple certs, dump the old one */
                     86:         RSA_free(*ctx);
                     87: 
                     88:     bi_ctx = bi_initialize();
                     89:     *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX));
                     90:     rsa_ctx = *ctx;
                     91:     rsa_ctx->bi_ctx = bi_ctx;
                     92:     rsa_ctx->num_octets = mod_len;
                     93:     rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len);
                     94:     bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET);
                     95:     rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len);
                     96:     bi_permanent(rsa_ctx->e);
                     97: }
                     98: 
                     99: /**
                    100:  * Free up any RSA context resources.
                    101:  */
                    102: void RSA_free(RSA_CTX *rsa_ctx)
                    103: {
                    104:     BI_CTX *bi_ctx;
                    105:     if (rsa_ctx == NULL)                /* deal with ptrs that are null */
                    106:         return;
                    107: 
                    108:     bi_ctx = rsa_ctx->bi_ctx;
                    109: 
                    110:     bi_depermanent(rsa_ctx->e);
                    111:     bi_free(bi_ctx, rsa_ctx->e);
                    112:     bi_free_mod(rsa_ctx->bi_ctx, BIGINT_M_OFFSET);
                    113: 
                    114:     if (rsa_ctx->d)
                    115:     {
                    116:         bi_depermanent(rsa_ctx->d);
                    117:         bi_free(bi_ctx, rsa_ctx->d);
                    118: #ifdef CONFIG_BIGINT_CRT
                    119:         bi_depermanent(rsa_ctx->dP);
                    120:         bi_depermanent(rsa_ctx->dQ);
                    121:         bi_depermanent(rsa_ctx->qInv);
                    122:         bi_free(bi_ctx, rsa_ctx->dP);
                    123:         bi_free(bi_ctx, rsa_ctx->dQ);
                    124:         bi_free(bi_ctx, rsa_ctx->qInv);
                    125:         bi_free_mod(rsa_ctx->bi_ctx, BIGINT_P_OFFSET);
                    126:         bi_free_mod(rsa_ctx->bi_ctx, BIGINT_Q_OFFSET);
                    127: #endif
                    128:     }
                    129: 
                    130:     bi_terminate(bi_ctx);
                    131:     free(rsa_ctx);
                    132: }
                    133: 
                    134: /**
                    135:  * @brief Use PKCS1.5 for decryption/verification.
                    136:  * @param ctx [in] The context
                    137:  * @param in_data [in] The data to encrypt (must be < modulus size-11)
                    138:  * @param out_data [out] The encrypted data.
                    139:  * @param is_decryption [in] Decryption or verify operation.
                    140:  * @return  The number of bytes that were originally encrypted. -1 on error.
                    141:  * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
                    142:  */
                    143: int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, 
                    144:                             uint8_t *out_data, int is_decryption)
                    145: {
                    146:     const int byte_size = ctx->num_octets;
                    147:     int i, size;
                    148:     bigint *decrypted_bi, *dat_bi;
                    149:     uint8_t *block = (uint8_t *)alloca(byte_size);
                    150: 
                    151:     memset(out_data, 0, byte_size); /* initialise */
                    152: 
                    153:     /* decrypt */
                    154:     dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size);
                    155: #ifdef CONFIG_SSL_CERT_VERIFICATION
                    156:     decrypted_bi = is_decryption ?  /* decrypt or verify? */
                    157:             RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi);
                    158: #else   /* always a decryption */
                    159:     decrypted_bi = RSA_private(ctx, dat_bi);
                    160: #endif
                    161: 
                    162:     /* convert to a normal block */
                    163:     bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size);
                    164: 
                    165:     i = 10; /* start at the first possible non-padded byte */
                    166: 
                    167: #ifdef CONFIG_SSL_CERT_VERIFICATION
                    168:     if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */
                    169:     {
                    170:         while (block[i++] == 0xff && i < byte_size);
                    171: 
                    172:         if (block[i-2] != 0xff)
                    173:             i = byte_size;     /*ensure size is 0 */   
                    174:     }
                    175:     else                    /* PKCS1.5 encryption padding is random */
                    176: #endif
                    177:     {
                    178:         while (block[i++] && i < byte_size);
                    179:     }
                    180:     size = byte_size - i;
                    181: 
                    182:     /* get only the bit we want */
                    183:     if (size > 0)
                    184:         memcpy(out_data, &block[i], size);
                    185:     
                    186:     return size ? size : -1;
                    187: }
                    188: 
                    189: /**
                    190:  * Performs m = c^d mod n
                    191:  */
                    192: bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)
                    193: {
                    194: #ifdef CONFIG_BIGINT_CRT
                    195:     return bi_crt(c->bi_ctx, bi_msg, c->dP, c->dQ, c->p, c->q, c->qInv);
                    196: #else
                    197:     BI_CTX *ctx = c->bi_ctx;
                    198:     ctx->mod_offset = BIGINT_M_OFFSET;
                    199:     return bi_mod_power(ctx, bi_msg, c->d);
                    200: #endif
                    201: }
                    202: 
                    203: #ifdef CONFIG_SSL_FULL_MODE
                    204: /**
                    205:  * Used for diagnostics.
                    206:  */
                    207: void RSA_print(const RSA_CTX *rsa_ctx) 
                    208: {
                    209:     if (rsa_ctx == NULL)
                    210:         return;
                    211: 
                    212:     printf("-----------------   RSA DEBUG   ----------------\n");
                    213:     printf("Size:\t%d\n", rsa_ctx->num_octets);
                    214:     bi_print("Modulus", rsa_ctx->m);
                    215:     bi_print("Public Key", rsa_ctx->e);
                    216:     bi_print("Private Key", rsa_ctx->d);
                    217: }
                    218: #endif
                    219: 
                    220: #if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
                    221: /**
                    222:  * Performs c = m^e mod n
                    223:  */
                    224: bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg)
                    225: {
                    226:     c->bi_ctx->mod_offset = BIGINT_M_OFFSET;
                    227:     return bi_mod_power(c->bi_ctx, bi_msg, c->e);
                    228: }
                    229: 
                    230: /**
                    231:  * Use PKCS1.5 for encryption/signing.
                    232:  * see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
                    233:  */
                    234: int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, 
                    235:         uint8_t *out_data, int is_signing)
                    236: {
                    237:     int byte_size = ctx->num_octets;
                    238:     int num_pads_needed = byte_size-in_len-3;
                    239:     bigint *dat_bi, *encrypt_bi;
                    240: 
                    241:     /* note: in_len+11 must be > byte_size */
                    242:     out_data[0] = 0;     /* ensure encryption block is < modulus */
                    243: 
                    244:     if (is_signing)
                    245:     {
                    246:         out_data[1] = 1;        /* PKCS1.5 signing pads with "0xff"'s */
                    247:         memset(&out_data[2], 0xff, num_pads_needed);
                    248:     }
                    249:     else /* randomize the encryption padding with non-zero bytes */   
                    250:     {
                    251:         out_data[1] = 2;
                    252:         get_random_NZ(num_pads_needed, &out_data[2]);
                    253:     }
                    254: 
                    255:     out_data[2+num_pads_needed] = 0;
                    256:     memcpy(&out_data[3+num_pads_needed], in_data, in_len);
                    257: 
                    258:     /* now encrypt it */
                    259:     dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size);
                    260:     encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) : 
                    261:                               RSA_public(ctx, dat_bi);
                    262:     bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size);
                    263: 
                    264:     /* save a few bytes of memory */
                    265:     bi_clear_cache(ctx->bi_ctx);
                    266:     return byte_size;
                    267: }
                    268: 
                    269: #endif  /* CONFIG_SSL_CERT_VERIFICATION */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>