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