Home | History | Annotate | Download | only in pkcs1
      1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
      2  *
      3  * LibTomCrypt is a library that provides various cryptographic
      4  * algorithms in a highly modular and flexible manner.
      5  *
      6  * The library is free for all purposes without any express
      7  * guarantee it works.
      8  *
      9  * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com
     10  */
     11 #include "tomcrypt.h"
     12 
     13 /**
     14   @file pkcs_1_oaep_encode.c
     15   OAEP Padding for PKCS #1, Tom St Denis
     16 */
     17 
     18 #ifdef PKCS_1
     19 
     20 /**
     21   PKCS #1 v2.00 OAEP encode
     22   @param msg             The data to encode
     23   @param msglen          The length of the data to encode (octets)
     24   @param lparam          A session or system parameter (can be NULL)
     25   @param lparamlen       The length of the lparam data
     26   @param modulus_bitlen  The bit length of the RSA modulus
     27   @param prng            An active PRNG state
     28   @param prng_idx        The index of the PRNG desired
     29   @param hash_idx        The index of the hash desired
     30   @param out             [out] The destination for the encoded data
     31   @param outlen          [in/out] The max size and resulting size of the encoded data
     32   @return CRYPT_OK if successful
     33 */
     34 int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
     35                        const unsigned char *lparam, unsigned long lparamlen,
     36                              unsigned long modulus_bitlen, prng_state *prng,
     37                              int           prng_idx,         int  hash_idx,
     38                              unsigned char *out,    unsigned long *outlen)
     39 {
     40    unsigned char *DB, *seed, *mask;
     41    unsigned long hLen, x, y, modulus_len;
     42    int           err;
     43 
     44    LTC_ARGCHK(msg    != NULL);
     45    LTC_ARGCHK(out    != NULL);
     46    LTC_ARGCHK(outlen != NULL);
     47 
     48    /* test valid hash */
     49    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
     50       return err;
     51    }
     52 
     53    /* valid prng */
     54    if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
     55       return err;
     56    }
     57 
     58    hLen        = hash_descriptor[hash_idx].hashsize;
     59    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
     60 
     61    /* test message size */
     62    if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) {
     63       return CRYPT_PK_INVALID_SIZE;
     64    }
     65 
     66    /* allocate ram for DB/mask/salt of size modulus_len */
     67    DB   = XMALLOC(modulus_len);
     68    mask = XMALLOC(modulus_len);
     69    seed = XMALLOC(hLen);
     70    if (DB == NULL || mask == NULL || seed == NULL) {
     71       if (DB != NULL) {
     72          XFREE(DB);
     73       }
     74       if (mask != NULL) {
     75          XFREE(mask);
     76       }
     77       if (seed != NULL) {
     78          XFREE(seed);
     79       }
     80       return CRYPT_MEM;
     81    }
     82 
     83    /* get lhash */
     84    /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
     85    x = modulus_len;
     86    if (lparam != NULL) {
     87       if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
     88          goto LBL_ERR;
     89       }
     90    } else {
     91       /* can't pass hash_memory a NULL so use DB with zero length */
     92       if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {
     93          goto LBL_ERR;
     94       }
     95    }
     96 
     97    /* append PS then 0x01 (to lhash)  */
     98    x = hLen;
     99    y = modulus_len - msglen - 2*hLen - 2;
    100    XMEMSET(DB+x, 0, y);
    101    x += y;
    102 
    103    /* 0x01 byte */
    104    DB[x++] = 0x01;
    105 
    106    /* message (length = msglen) */
    107    XMEMCPY(DB+x, msg, msglen);
    108    x += msglen;
    109 
    110    /* now choose a random seed */
    111    if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) {
    112       err = CRYPT_ERROR_READPRNG;
    113       goto LBL_ERR;
    114    }
    115 
    116    /* compute MGF1 of seed (k - hlen - 1) */
    117    if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
    118       goto LBL_ERR;
    119    }
    120 
    121    /* xor against DB */
    122    for (y = 0; y < (modulus_len - hLen - 1); y++) {
    123        DB[y] ^= mask[y];
    124    }
    125 
    126    /* compute MGF1 of maskedDB (hLen) */
    127    if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
    128       goto LBL_ERR;
    129    }
    130 
    131    /* XOR against seed */
    132    for (y = 0; y < hLen; y++) {
    133       seed[y] ^= mask[y];
    134    }
    135 
    136    /* create string of length modulus_len */
    137    if (*outlen < modulus_len) {
    138       *outlen = modulus_len;
    139       err = CRYPT_BUFFER_OVERFLOW;
    140       goto LBL_ERR;
    141    }
    142 
    143    /* start output which is 0x00 || maskedSeed || maskedDB */
    144    x = 0;
    145    out[x++] = 0x00;
    146    XMEMCPY(out+x, seed, hLen);
    147    x += hLen;
    148    XMEMCPY(out+x, DB, modulus_len - hLen - 1);
    149    x += modulus_len - hLen - 1;
    150 
    151    *outlen = x;
    152 
    153    err = CRYPT_OK;
    154 LBL_ERR:
    155 #ifdef LTC_CLEAN_STACK
    156    zeromem(DB,   modulus_len);
    157    zeromem(seed, hLen);
    158    zeromem(mask, modulus_len);
    159 #endif
    160 
    161    XFREE(seed);
    162    XFREE(mask);
    163    XFREE(DB);
    164 
    165    return err;
    166 }
    167 
    168 #endif /* PKCS_1 */
    169 
    170 
    171 /* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c,v $ */
    172 /* $Revision: 1.7 $ */
    173 /* $Date: 2006/06/16 21:53:41 $ */
    174