X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=test%2Frsa_test.c;h=cd9ca7f13c184d231f4c99bfbb4c96b8abf973ba;hp=0b707bf715ec7981ce5b43a3680d4896ea29e19a;hb=459217237640369a092084ccb80175b5758f40b1;hpb=c2e27310c790c0dd2f87dd420e65e0cca522ddb2 diff --git a/test/rsa_test.c b/test/rsa_test.c index 0b707bf715..cd9ca7f13c 100644 --- a/test/rsa_test.c +++ b/test/rsa_test.c @@ -1,34 +1,49 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + /* test vectors from p1ovect1.txt */ #include #include -#include "e_os.h" +#include "internal/nelem.h" #include #include #include #include + +#include "testutil.h" + #ifdef OPENSSL_NO_RSA -int main(int argc, char *argv[]) +int setup_tests(void) { - printf("No RSA support\n"); - return (0); + /* No tests */ + return 1; } #else # include # define SetKey \ - key->n = BN_bin2bn(n, sizeof(n)-1, key->n); \ - key->e = BN_bin2bn(e, sizeof(e)-1, key->e); \ - key->d = BN_bin2bn(d, sizeof(d)-1, key->d); \ - key->p = BN_bin2bn(p, sizeof(p)-1, key->p); \ - key->q = BN_bin2bn(q, sizeof(q)-1, key->q); \ - key->dmp1 = BN_bin2bn(dmp1, sizeof(dmp1)-1, key->dmp1); \ - key->dmq1 = BN_bin2bn(dmq1, sizeof(dmq1)-1, key->dmq1); \ - key->iqmp = BN_bin2bn(iqmp, sizeof(iqmp)-1, key->iqmp); \ - memcpy(c, ctext_ex, sizeof(ctext_ex) - 1); \ - return (sizeof(ctext_ex) - 1); + RSA_set0_key(key, \ + BN_bin2bn(n, sizeof(n)-1, NULL), \ + BN_bin2bn(e, sizeof(e)-1, NULL), \ + BN_bin2bn(d, sizeof(d)-1, NULL)); \ + RSA_set0_factors(key, \ + BN_bin2bn(p, sizeof(p)-1, NULL), \ + BN_bin2bn(q, sizeof(q)-1, NULL)); \ + RSA_set0_crt_params(key, \ + BN_bin2bn(dmp1, sizeof(dmp1)-1, NULL), \ + BN_bin2bn(dmq1, sizeof(dmq1)-1, NULL), \ + BN_bin2bn(iqmp, sizeof(iqmp)-1, NULL)); \ + memcpy(c, ctext_ex, sizeof(ctext_ex) - 1); \ + return sizeof(ctext_ex) - 1; static int key1(RSA *key, unsigned char *c) { @@ -201,17 +216,31 @@ static int pad_unknown(void) unsigned long l; while ((l = ERR_get_error()) != 0) if (ERR_GET_REASON(l) == RSA_R_UNKNOWN_PADDING_TYPE) - return (1); - return (0); + return 1; + return 0; } -static const char rnd_seed[] = - "string to make the random number generator think it has entropy"; +static int rsa_setkey(RSA** key, unsigned char* ctext, int idx) +{ + int clen = 0; + *key = RSA_new(); + switch (idx) { + case 0: + clen = key1(*key, ctext); + break; + case 1: + clen = key2(*key, ctext); + break; + case 2: + clen = key3(*key, ctext); + break; + } + return clen; +} -int main(int argc, char *argv[]) +static int test_rsa_pkcs1(int idx) { - int err = 0; - int v; + int ret = 0; RSA *key; unsigned char ptext[256]; unsigned char ctext[256]; @@ -220,121 +249,150 @@ int main(int argc, char *argv[]) int plen; int clen = 0; int num; - int n; - CRYPTO_set_mem_debug(1); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + plen = sizeof(ptext_ex) - 1; + clen = rsa_setkey(&key, ctext_ex, idx); - RAND_seed(rnd_seed, sizeof rnd_seed); /* or OAEP may fail */ + num = RSA_public_encrypt(plen, ptext_ex, ctext, key, + RSA_PKCS1_PADDING); + if (!TEST_int_eq(num, clen)) + goto err; - plen = sizeof(ptext_ex) - 1; + num = RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_PADDING); + if (!TEST_mem_eq(ptext, num, ptext_ex, plen)) + goto err; - for (v = 0; v < 6; v++) { - key = RSA_new(); - switch (v % 3) { - case 0: - clen = key1(key, ctext_ex); - break; - case 1: - clen = key2(key, ctext_ex); - break; - case 2: - clen = key3(key, ctext_ex); - break; - } - if (v / 3 >= 1) - key->flags |= RSA_FLAG_NO_CONSTTIME; - - num = RSA_public_encrypt(plen, ptext_ex, ctext, key, - RSA_PKCS1_PADDING); - if (num != clen) { - printf("PKCS#1 v1.5 encryption failed!\n"); - err = 1; - goto oaep; - } - - num = RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_PADDING); - if (num != plen || memcmp(ptext, ptext_ex, num) != 0) { - printf("PKCS#1 v1.5 decryption failed!\n"); - err = 1; - } else - printf("PKCS #1 v1.5 encryption/decryption ok\n"); - - oaep: - ERR_clear_error(); - num = RSA_public_encrypt(plen, ptext_ex, ctext, key, - RSA_PKCS1_OAEP_PADDING); - if (num == -1 && pad_unknown()) { - printf("No OAEP support\n"); - goto next; - } - if (num != clen) { - printf("OAEP encryption failed!\n"); - err = 1; - goto next; - } - - num = RSA_private_decrypt(num, ctext, ptext, key, - RSA_PKCS1_OAEP_PADDING); - if (num != plen || memcmp(ptext, ptext_ex, num) != 0) { - printf("OAEP decryption (encrypted data) failed!\n"); - err = 1; - } else if (memcmp(ctext, ctext_ex, num) == 0) - printf("OAEP test vector %d passed!\n", v); - - /* - * Different ciphertexts (rsa_oaep.c without -DPKCS_TESTVECT). Try - * decrypting ctext_ex - */ - - num = RSA_private_decrypt(clen, ctext_ex, ptext, key, - RSA_PKCS1_OAEP_PADDING); + ret = 1; +err: + RSA_free(key); + return ret; +} + +static int test_rsa_oaep(int idx) +{ + int ret = 0; + RSA *key; + unsigned char ptext[256]; + unsigned char ctext[256]; + static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; + unsigned char ctext_ex[256]; + int plen; + int clen = 0; + int num; + int n; - if (num != plen || memcmp(ptext, ptext_ex, num) != 0) { - printf("OAEP decryption (test vector data) failed!\n"); - err = 1; - } else - printf("OAEP encryption/decryption ok\n"); - - /* Try decrypting corrupted ciphertexts. */ - for (n = 0; n < clen; ++n) { - ctext[n] ^= 1; - num = RSA_private_decrypt(clen, ctext, ptext, key, - RSA_PKCS1_OAEP_PADDING); - if (num > 0) { - printf("Corrupt data decrypted!\n"); - err = 1; - break; - } - ctext[n] ^= 1; - } - - /* Test truncated ciphertexts, as well as negative length. */ - for (n = -1; n < clen; ++n) { - num = RSA_private_decrypt(n, ctext, ptext, key, + plen = sizeof(ptext_ex) - 1; + clen = rsa_setkey(&key, ctext_ex, idx); + + num = RSA_public_encrypt(plen, ptext_ex, ctext, key, + RSA_PKCS1_OAEP_PADDING); + if (num == -1 && pad_unknown()) { + TEST_info("Skipping: No OAEP support"); + ret = 1; + goto err; + } + if (!TEST_int_eq(num, clen)) + goto err; + + num = RSA_private_decrypt(num, ctext, ptext, key, + RSA_PKCS1_OAEP_PADDING); + if (!TEST_mem_eq(ptext, num, ptext_ex, plen)) + goto err; + + /* Different ciphertexts. Try decrypting ctext_ex */ + num = RSA_private_decrypt(clen, ctext_ex, ptext, key, + RSA_PKCS1_OAEP_PADDING); + if (!TEST_mem_eq(ptext, num, ptext_ex, plen)) + goto err; + + /* Try decrypting corrupted ciphertexts. */ + for (n = 0; n < clen; ++n) { + ctext[n] ^= 1; + num = RSA_private_decrypt(clen, ctext, ptext, key, RSA_PKCS1_OAEP_PADDING); - if (num > 0) { - printf("Truncated data decrypted!\n"); - err = 1; - break; - } - } - - next: - RSA_free(key); + if (!TEST_int_le(num, 0)) + goto err; + ctext[n] ^= 1; } - CRYPTO_cleanup_all_ex_data(); - ERR_remove_thread_state(NULL); + /* Test truncated ciphertexts, as well as negative length. */ + for (n = -1; n < clen; ++n) { + num = RSA_private_decrypt(n, ctext, ptext, key, + RSA_PKCS1_OAEP_PADDING); + if (!TEST_int_le(num, 0)) + goto err; + } -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - CRYPTO_mem_leaks_fp(stderr); -#endif + ret = 1; +err: + RSA_free(key); + return ret; +} -# ifdef OPENSSL_SYS_NETWARE - if (err) - printf("ERROR: %d\n", err); -# endif - return err; +static const struct { + int bits; + unsigned int r; +} rsa_security_bits_cases[] = { + /* NIST SP 800-56B rev 2 (draft) Appendix D Table 5 */ + { 2048, 112 }, + { 3072, 128 }, + { 4096, 152 }, + { 6144, 176 }, + { 8192, 200 }, + /* Older values */ + { 256, 40 }, + { 512, 56 }, + { 1024, 80 }, + /* Slightly different value to the 256 that NIST lists in their tables */ + { 15360, 264 }, + /* Some other values */ + { 8888, 208 }, + { 2468, 120 }, + { 13456, 248 } +}; + +static int test_rsa_security_bit(int n) +{ + static const unsigned char vals[8] = { + 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40 + }; + RSA *key = RSA_new(); + const int bits = rsa_security_bits_cases[n].bits; + const int result = rsa_security_bits_cases[n].r; + const int bytes = (bits + 7) / 8; + int r = 0; + unsigned char num[2000]; + + if (!TEST_ptr(key) || !TEST_int_le(bytes, (int)sizeof(num))) + goto err; + + /* + * It is necessary to set the RSA key in order to ask for the strength. + * A BN of an appropriate size is created, in general it won't have the + * properties necessary for RSA to function. This is okay here since + * the RSA key is never used. + */ + memset(num, vals[bits % 8], bytes); + + /* + * The 'e' parameter is set to the same value as 'n'. This saves having + * an extra BN to hold a sensible value for 'e'. This is safe since the + * RSA key is not used. The 'd' parameter can be NULL safely. + */ + if (TEST_true(RSA_set0_key(key, BN_bin2bn(num, bytes, NULL), + BN_bin2bn(num, bytes, NULL), NULL)) + && TEST_uint_eq(RSA_security_bits(key), result)) + r = 1; +err: + RSA_free(key); + return r; +} + +int setup_tests(void) +{ + ADD_ALL_TESTS(test_rsa_pkcs1, 3); + ADD_ALL_TESTS(test_rsa_oaep, 3); + ADD_ALL_TESTS(test_rsa_security_bit, OSSL_NELEM(rsa_security_bits_cases)); + return 1; } #endif