1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner. 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works. 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h" 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @file pkcs_1_oaep_decode.c 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project OAEP Padding for PKCS #1, Tom St Denis 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef PKCS_1 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PKCS #1 v2.00 OAEP decode 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param msg The encoded data to decode 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param msglen The length of the encoded data (octets) 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param lparam The session or system data (can be NULL) 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param lparamlen The length of the lparam 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param modulus_bitlen The bit length of the RSA modulus 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param hash_idx The index of the hash desired 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param out [out] Destination of decoding 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param outlen [in/out] The max size and resulting size of the decoding 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param res [out] Result of decoding, 1==valid, 0==invalid 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if successful (even if invalid) 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const unsigned char *lparam, unsigned long lparamlen, 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long modulus_bitlen, int hash_idx, 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *out, unsigned long *outlen, 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int *res) 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *DB, *seed, *mask; 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long hLen, x, y, modulus_len; 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int err; 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(msg != NULL); 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(out != NULL); 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(outlen != NULL); 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(res != NULL); 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* default to invalid packet */ 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *res = 0; 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* test valid hash */ 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hLen = hash_descriptor[hash_idx].hashsize; 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* test hash/message size */ 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) { 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_PK_INVALID_SIZE; 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* allocate ram for DB/mask/salt of size modulus_len */ 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project DB = XMALLOC(modulus_len); 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mask = XMALLOC(modulus_len); 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project seed = XMALLOC(hLen); 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (DB == NULL || mask == NULL || seed == NULL) { 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (DB != NULL) { 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(DB); 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mask != NULL) { 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(mask); 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (seed != NULL) { 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(seed); 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_MEM; 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* ok so it's now in the form 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x00 || maskedseed || maskedDB 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 1 || hLen || modulus_len - hLen - 1 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* must have leading 0x00 byte */ 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (msg[0] != 0x00) { 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_OK; 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now read the masked seed */ 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 1; 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XMEMCPY(seed, msg + x, hLen); 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x += hLen; 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now read the masked DB */ 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XMEMCPY(DB, msg + x, modulus_len - hLen - 1); 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x += modulus_len - hLen - 1; 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* compute MGF1 of maskedDB (hLen) */ 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* XOR against seed */ 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < hLen; y++) { 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project seed[y] ^= mask[y]; 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* compute MGF1 of seed (k - hlen - 1) */ 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* xor against DB */ 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < (modulus_len - hLen - 1); y++) { 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project DB[y] ^= mask[y]; 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* compute lhash and store it in seed [reuse temps!] */ 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = modulus_len; 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (lparam != NULL) { 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* can't pass hash_memory a NULL so use DB with zero length */ 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* compare the lhash'es */ 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (XMEMCMP(seed, DB, hLen) != 0) { 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_OK; 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now zeroes before a 0x01 */ 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* step... */ 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* error out if wasn't 0x01 */ 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_INVALID_PACKET; 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* rest is the message (and skip 0x01) */ 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((modulus_len - hLen - 1 - ++x) > *outlen) { 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *outlen = modulus_len - hLen - 1 - x; 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_BUFFER_OVERFLOW; 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto LBL_ERR; 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* copy message */ 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *outlen = modulus_len - hLen - 1 - x; 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x += modulus_len - hLen - 1; 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* valid packet */ 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *res = 1; 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project err = CRYPT_OK; 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source ProjectLBL_ERR: 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(DB, modulus_len); 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(seed, hLen); 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(mask, modulus_len); 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(seed); 179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(mask); 180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(DB); 181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* PKCS_1 */ 186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c,v $ */ 188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.11 $ */ 189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/01 09:28:17 $ */ 190