diff options
author | Bob Beck <beck@cvs.openbsd.org> | 1999-09-29 04:37:45 +0000 |
---|---|---|
committer | Bob Beck <beck@cvs.openbsd.org> | 1999-09-29 04:37:45 +0000 |
commit | 30902ef04e4a800063b5f4afdbf1732ad34aa6b3 (patch) | |
tree | 1521f29ad032f1ab16a7838557a8c1e28f1414e1 /lib/libcrypto/rsa/rsa_oaep.c | |
parent | 68e1384c87c6264544ffca6394cdb172d13acde7 (diff) |
import openssl-0.9.7-beta1
Diffstat (limited to 'lib/libcrypto/rsa/rsa_oaep.c')
-rw-r--r-- | lib/libcrypto/rsa/rsa_oaep.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/libcrypto/rsa/rsa_oaep.c b/lib/libcrypto/rsa/rsa_oaep.c new file mode 100644 index 00000000000..843c40c8640 --- /dev/null +++ b/lib/libcrypto/rsa/rsa_oaep.c @@ -0,0 +1,162 @@ +/* crypto/rsa/rsa_oaep.c */ +/* Written by Ulf Moeller. This software is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. */ + +/* EME_OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ + +#if !defined(NO_SHA) && !defined(NO_SHA1) +#include <stdio.h> +#include "cryptlib.h" +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/sha.h> +#include <openssl/rand.h> + +int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen); + +int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + unsigned char *from, int flen, unsigned char *param, int plen) + { + int i, emlen = tlen - 1; + unsigned char *db, *seed; + unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH]; + + if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return (0); + } + + if (emlen < 2 * SHA_DIGEST_LENGTH + 1) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL); + return (0); + } + + dbmask = Malloc(emlen - SHA_DIGEST_LENGTH); + if (dbmask == NULL) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); + return (0); + } + + to[0] = 0; + seed = to + 1; + db = to + SHA_DIGEST_LENGTH + 1; + + SHA1(param, plen, db); + memset(db + SHA_DIGEST_LENGTH, 0, + emlen - flen - 2 * SHA_DIGEST_LENGTH - 1); + db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01; + memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen); + RAND_bytes(seed, SHA_DIGEST_LENGTH); +#ifdef PKCS_TESTVECT + memcpy(seed, + "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f", + 20); +#endif + + MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH); + for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++) + db[i] ^= dbmask[i]; + + MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH); + for (i = 0; i < SHA_DIGEST_LENGTH; i++) + seed[i] ^= seedmask[i]; + + Free(dbmask); + return (1); + } + +int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + unsigned char *from, int flen, int num, unsigned char *param, + int plen) + { + int i, dblen, mlen = -1; + unsigned char *maskeddb; + int lzero; + unsigned char *db, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH]; + + if (--num < 2 * SHA_DIGEST_LENGTH + 1) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); + return (-1); + } + + dblen = num - SHA_DIGEST_LENGTH; + db = Malloc(dblen); + if (db == NULL) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); + return (-1); + } + + lzero = num - flen; + maskeddb = from - lzero + SHA_DIGEST_LENGTH; + + MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen); + for (i = lzero; i < SHA_DIGEST_LENGTH; i++) + seed[i] ^= from[i - lzero]; + + MGF1(db, dblen, seed, SHA_DIGEST_LENGTH); + for (i = 0; i < dblen; i++) + db[i] ^= maskeddb[i]; + + SHA1(param, plen, phash); + + if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0) + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); + else + { + for (i = SHA_DIGEST_LENGTH; i < dblen; i++) + if (db[i] != 0x00) + break; + if (db[i] != 0x01 || i++ >= dblen) + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, + RSA_R_OAEP_DECODING_ERROR); + else + { + mlen = dblen - i; + if (tlen < mlen) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); + mlen = -1; + } + else + memcpy(to, db + i, mlen); + } + } + Free(db); + return (mlen); + } + +int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen) + { + long i, outlen = 0; + unsigned char cnt[4]; + SHA_CTX c; + unsigned char md[SHA_DIGEST_LENGTH]; + + for (i = 0; outlen < len; i++) + { + cnt[0] = (i >> 24) & 255, cnt[1] = (i >> 16) & 255, + cnt[2] = (i >> 8) & 255, cnt[3] = i & 255; + SHA1_Init(&c); + SHA1_Update(&c, seed, seedlen); + SHA1_Update(&c, cnt, 4); + if (outlen + SHA_DIGEST_LENGTH <= len) + { + SHA1_Final(mask + outlen, &c); + outlen += SHA_DIGEST_LENGTH; + } + else + { + SHA1_Final(md, &c); + memcpy(mask + outlen, md, len - outlen); + outlen = len; + } + } + return (0); + } +#endif |