1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/rsa/rsa_oaep.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,213 @@
1.4 +/* crypto/rsa/rsa_oaep.c */
1.5 +/* Written by Ulf Moeller. This software is distributed on an "AS IS"
1.6 + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. */
1.7 +
1.8 +/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */
1.9 +
1.10 +/* See Victor Shoup, "OAEP reconsidered," Nov. 2000,
1.11 + * <URL: http://www.shoup.net/papers/oaep.ps.Z>
1.12 + * for problems with the security proof for the
1.13 + * original OAEP scheme, which EME-OAEP is based on.
1.14 + *
1.15 + * A new proof can be found in E. Fujisaki, T. Okamoto,
1.16 + * D. Pointcheval, J. Stern, "RSA-OEAP is Still Alive!",
1.17 + * Dec. 2000, <URL: http://eprint.iacr.org/2000/061/>.
1.18 + * The new proof has stronger requirements for the
1.19 + * underlying permutation: "partial-one-wayness" instead
1.20 + * of one-wayness. For the RSA function, this is
1.21 + * an equivalent notion.
1.22 + */
1.23 +
1.24 +
1.25 +#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
1.26 +#include <stdio.h>
1.27 +#include "cryptlib.h"
1.28 +#include <openssl/bn.h>
1.29 +#include <openssl/rsa.h>
1.30 +#include <openssl/evp.h>
1.31 +#include <openssl/rand.h>
1.32 +#include <openssl/sha.h>
1.33 +
1.34 +EXPORT_C int MGF1(unsigned char *mask, long len,
1.35 + const unsigned char *seed, long seedlen);
1.36 +
1.37 +EXPORT_C int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
1.38 + const unsigned char *from, int flen,
1.39 + const unsigned char *param, int plen)
1.40 + {
1.41 + int i, emlen = tlen - 1;
1.42 + unsigned char *db, *seed;
1.43 + unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH];
1.44 +
1.45 + if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1)
1.46 + {
1.47 + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
1.48 + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
1.49 + return 0;
1.50 + }
1.51 +
1.52 + if (emlen < 2 * SHA_DIGEST_LENGTH + 1)
1.53 + {
1.54 + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL);
1.55 + return 0;
1.56 + }
1.57 +
1.58 + dbmask = OPENSSL_malloc(emlen - SHA_DIGEST_LENGTH);
1.59 + if (dbmask == NULL)
1.60 + {
1.61 + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
1.62 + return 0;
1.63 + }
1.64 +
1.65 + to[0] = 0;
1.66 + seed = to + 1;
1.67 + db = to + SHA_DIGEST_LENGTH + 1;
1.68 +
1.69 + EVP_Digest((void *)param, plen, db, NULL, EVP_sha1(), NULL);
1.70 + memset(db + SHA_DIGEST_LENGTH, 0,
1.71 + emlen - flen - 2 * SHA_DIGEST_LENGTH - 1);
1.72 + db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01;
1.73 + memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen);
1.74 + if (RAND_bytes(seed, SHA_DIGEST_LENGTH) <= 0)
1.75 + return 0;
1.76 +#ifdef PKCS_TESTVECT
1.77 + memcpy(seed,
1.78 + "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
1.79 + 20);
1.80 +#endif
1.81 +
1.82 + MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH);
1.83 + for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++)
1.84 + db[i] ^= dbmask[i];
1.85 +
1.86 + MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH);
1.87 + for (i = 0; i < SHA_DIGEST_LENGTH; i++)
1.88 + seed[i] ^= seedmask[i];
1.89 +
1.90 + OPENSSL_free(dbmask);
1.91 + return 1;
1.92 + }
1.93 +
1.94 +EXPORT_C int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
1.95 + const unsigned char *from, int flen, int num,
1.96 + const unsigned char *param, int plen)
1.97 + {
1.98 + int i, dblen, mlen = -1;
1.99 + const unsigned char *maskeddb;
1.100 + int lzero;
1.101 + unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH];
1.102 + int bad = 0;
1.103 +
1.104 + if (--num < 2 * SHA_DIGEST_LENGTH + 1)
1.105 + /* 'num' is the length of the modulus, i.e. does not depend on the
1.106 + * particular ciphertext. */
1.107 + goto decoding_err;
1.108 +
1.109 + lzero = num - flen;
1.110 + if (lzero < 0)
1.111 + {
1.112 + /* lzero == -1 */
1.113 +
1.114 + /* signalling this error immediately after detection might allow
1.115 + * for side-channel attacks (e.g. timing if 'plen' is huge
1.116 + * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal
1.117 + * Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001),
1.118 + * so we use a 'bad' flag */
1.119 + bad = 1;
1.120 + lzero = 0;
1.121 + }
1.122 + maskeddb = from - lzero + SHA_DIGEST_LENGTH;
1.123 +
1.124 + dblen = num - SHA_DIGEST_LENGTH;
1.125 + db = OPENSSL_malloc(dblen);
1.126 + if (db == NULL)
1.127 + {
1.128 + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
1.129 + return -1;
1.130 + }
1.131 +
1.132 + MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen);
1.133 + for (i = lzero; i < SHA_DIGEST_LENGTH; i++)
1.134 + seed[i] ^= from[i - lzero];
1.135 +
1.136 + MGF1(db, dblen, seed, SHA_DIGEST_LENGTH);
1.137 + for (i = 0; i < dblen; i++)
1.138 + db[i] ^= maskeddb[i];
1.139 +
1.140 + EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL);
1.141 +
1.142 + if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad)
1.143 + goto decoding_err;
1.144 + else
1.145 + {
1.146 + for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
1.147 + if (db[i] != 0x00)
1.148 + break;
1.149 + if (db[i] != 0x01 || i++ >= dblen)
1.150 + goto decoding_err;
1.151 + else
1.152 + {
1.153 + /* everything looks OK */
1.154 +
1.155 + mlen = dblen - i;
1.156 + if (tlen < mlen)
1.157 + {
1.158 + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);
1.159 + mlen = -1;
1.160 + }
1.161 + else
1.162 + memcpy(to, db + i, mlen);
1.163 + }
1.164 + }
1.165 + OPENSSL_free(db);
1.166 + return mlen;
1.167 +
1.168 +decoding_err:
1.169 + /* to avoid chosen ciphertext attacks, the error message should not reveal
1.170 + * which kind of decoding error happened */
1.171 + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR);
1.172 + if (db != NULL) OPENSSL_free(db);
1.173 + return -1;
1.174 + }
1.175 +
1.176 +EXPORT_C int PKCS1_MGF1(unsigned char *mask, long len,
1.177 + const unsigned char *seed, long seedlen, const EVP_MD *dgst)
1.178 + {
1.179 + long i, outlen = 0;
1.180 + unsigned char cnt[4];
1.181 + EVP_MD_CTX c;
1.182 + unsigned char md[EVP_MAX_MD_SIZE];
1.183 + int mdlen;
1.184 +
1.185 + EVP_MD_CTX_init(&c);
1.186 + mdlen = EVP_MD_size(dgst);
1.187 + for (i = 0; outlen < len; i++)
1.188 + {
1.189 + cnt[0] = (unsigned char)((i >> 24) & 255);
1.190 + cnt[1] = (unsigned char)((i >> 16) & 255);
1.191 + cnt[2] = (unsigned char)((i >> 8)) & 255;
1.192 + cnt[3] = (unsigned char)(i & 255);
1.193 + EVP_DigestInit_ex(&c,dgst, NULL);
1.194 + EVP_DigestUpdate(&c, seed, seedlen);
1.195 + EVP_DigestUpdate(&c, cnt, 4);
1.196 + if (outlen + mdlen <= len)
1.197 + {
1.198 + EVP_DigestFinal_ex(&c, mask + outlen, NULL);
1.199 + outlen += mdlen;
1.200 + }
1.201 + else
1.202 + {
1.203 + EVP_DigestFinal_ex(&c, md, NULL);
1.204 + memcpy(mask + outlen, md, len - outlen);
1.205 + outlen = len;
1.206 + }
1.207 + }
1.208 + EVP_MD_CTX_cleanup(&c);
1.209 + return 0;
1.210 + }
1.211 +
1.212 +EXPORT_C int MGF1(unsigned char *mask, long len, const unsigned char *seed, long seedlen)
1.213 + {
1.214 + return PKCS1_MGF1(mask, len, seed, seedlen, EVP_sha1());
1.215 + }
1.216 +#endif