original files of m241
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
static struct {
|
||||
unsigned char key[16];
|
||||
unsigned char plaintext[16];
|
||||
unsigned char ciphertext[16];
|
||||
} tests[] = {
|
||||
{
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
0x0B, 0x0C, 0x0D, 0x0E, 0x0F
|
||||
}, {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
|
||||
0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
||||
}, {
|
||||
0x69, 0xC4, 0xE0, 0xD8, 0x6A, 0x7B, 0x04, 0x30, 0xD8, 0xCD, 0xB7,
|
||||
0x80, 0x70, 0xB4, 0xC5, 0x5A
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
void FIPS_corrupt_aes()
|
||||
{
|
||||
tests[0].key[0]++;
|
||||
}
|
||||
|
||||
int FIPS_selftest_aes()
|
||||
{
|
||||
int n;
|
||||
int ret = 0;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
|
||||
for (n = 0; n < 1; ++n) {
|
||||
if (fips_cipher_test(&ctx, EVP_aes_128_ecb(),
|
||||
tests[n].key, NULL,
|
||||
tests[n].plaintext,
|
||||
tests[n].ciphertext, 16) <= 0)
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
if (ret == 0)
|
||||
FIPSerr(FIPS_F_FIPS_SELFTEST_AES, FIPS_R_SELFTEST_FAILED);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,147 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
static struct {
|
||||
unsigned char key[16];
|
||||
unsigned char plaintext[8];
|
||||
unsigned char ciphertext[8];
|
||||
} tests2[] = {
|
||||
{
|
||||
{
|
||||
0x7c, 0x4f, 0x6e, 0xf7, 0xa2, 0x04, 0x16, 0xec, 0x0b, 0x6b, 0x7c,
|
||||
0x9e, 0x5e, 0x19, 0xa7, 0xc4
|
||||
}, {
|
||||
0x06, 0xa7, 0xd8, 0x79, 0xaa, 0xce, 0x69, 0xef
|
||||
}, {
|
||||
0x4c, 0x11, 0x17, 0x55, 0xbf, 0xc4, 0x4e, 0xfd
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
0x5d, 0x9e, 0x01, 0xd3, 0x25, 0xc7, 0x3e, 0x34, 0x01, 0x16, 0x7c,
|
||||
0x85, 0x23, 0xdf, 0xe0, 0x68
|
||||
}, {
|
||||
0x9c, 0x50, 0x09, 0x0f, 0x5e, 0x7d, 0x69, 0x7e
|
||||
}, {
|
||||
0xd2, 0x0b, 0x18, 0xdf, 0xd9, 0x0d, 0x9e, 0xff
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct {
|
||||
unsigned char key[24];
|
||||
unsigned char plaintext[8];
|
||||
unsigned char ciphertext[8];
|
||||
} tests3[] = {
|
||||
{
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, 0xBA,
|
||||
0x98, 0x76, 0x54, 0x32, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
|
||||
0xde, 0xf0
|
||||
}, {
|
||||
0x8f, 0x8f, 0xbf, 0x9b, 0x5d, 0x48, 0xb4, 0x1c
|
||||
}, {
|
||||
0x59, 0x8c, 0xe5, 0xd3, 0x6c, 0xa2, 0xea, 0x1b
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0x01, 0x23, 0x45,
|
||||
0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xED, 0x39, 0xD9, 0x50, 0xFA, 0x74,
|
||||
0xBC, 0xC4
|
||||
}, {
|
||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
|
||||
}, {
|
||||
0x11, 0x25, 0xb0, 0x35, 0xbe, 0xa0, 0x82, 0x86
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
void FIPS_corrupt_des()
|
||||
{
|
||||
tests2[0].plaintext[0]++;
|
||||
}
|
||||
|
||||
int FIPS_selftest_des()
|
||||
{
|
||||
int n, ret = 0;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
/* Encrypt/decrypt with 2-key 3DES and compare to known answers */
|
||||
for (n = 0; n < 2; ++n) {
|
||||
if (!fips_cipher_test(&ctx, EVP_des_ede_ecb(),
|
||||
tests2[n].key, NULL,
|
||||
tests2[n].plaintext, tests2[n].ciphertext, 8))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Encrypt/decrypt with 3DES and compare to known answers */
|
||||
for (n = 0; n < 2; ++n) {
|
||||
if (!fips_cipher_test(&ctx, EVP_des_ede3_ecb(),
|
||||
tests3[n].key, NULL,
|
||||
tests3[n].plaintext, tests3[n].ciphertext, 8))
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
if (ret == 0)
|
||||
FIPSerr(FIPS_F_FIPS_SELFTEST_DES, FIPS_R_SELFTEST_FAILED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
/* crypto/dh/dh_gen.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
/*
|
||||
* NB: These functions have been upgraded - the previous prototypes are in
|
||||
* dh_depr.c as wrappers to these ones. - Geoff
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#ifndef OPENSSL_FIPS
|
||||
|
||||
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb);
|
||||
|
||||
int DH_generate_parameters_ex(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
if (ret->meth->generate_params)
|
||||
return ret->meth->generate_params(ret, prime_len, generator, cb);
|
||||
return dh_builtin_genparams(ret, prime_len, generator, cb);
|
||||
}
|
||||
|
||||
/*-
|
||||
* We generate DH parameters as follows
|
||||
* find a prime q which is prime_len/2 bits long.
|
||||
* p=(2*q)+1 or (p-1)/2 = q
|
||||
* For this case, g is a generator if
|
||||
* g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
|
||||
* Since the factors of p-1 are q and 2, we just need to check
|
||||
* g^2 mod p != 1 and g^q mod p != 1.
|
||||
*
|
||||
* Having said all that,
|
||||
* there is another special case method for the generators 2, 3 and 5.
|
||||
* for 2, p mod 24 == 11
|
||||
* for 3, p mod 12 == 5 <<<<< does not work for safe primes.
|
||||
* for 5, p mod 10 == 3 or 7
|
||||
*
|
||||
* Thanks to Phil Karn <karn@qualcomm.com> for the pointers about the
|
||||
* special generators and for answering some of my questions.
|
||||
*
|
||||
* I've implemented the second simple method :-).
|
||||
* Since DH should be using a safe prime (both p and q are prime),
|
||||
* this generator function can take a very very long time to run.
|
||||
*/
|
||||
/*
|
||||
* Actually there is no reason to insist that 'generator' be a generator.
|
||||
* It's just as OK (and in some sense better) to use a generator of the
|
||||
* order-q subgroup.
|
||||
*/
|
||||
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *t1, *t2;
|
||||
int g, ok = -1;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
t2 = BN_CTX_get(ctx);
|
||||
if (t1 == NULL || t2 == NULL)
|
||||
goto err;
|
||||
|
||||
/* Make sure 'ret' has the necessary elements */
|
||||
if (!ret->p && ((ret->p = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!ret->g && ((ret->g = BN_new()) == NULL))
|
||||
goto err;
|
||||
|
||||
if (generator <= 1) {
|
||||
DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
|
||||
goto err;
|
||||
}
|
||||
if (generator == DH_GENERATOR_2) {
|
||||
if (!BN_set_word(t1, 24))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 11))
|
||||
goto err;
|
||||
g = 2;
|
||||
}
|
||||
# if 0 /* does not work for safe primes */
|
||||
else if (generator == DH_GENERATOR_3) {
|
||||
if (!BN_set_word(t1, 12))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 5))
|
||||
goto err;
|
||||
g = 3;
|
||||
}
|
||||
# endif
|
||||
else if (generator == DH_GENERATOR_5) {
|
||||
if (!BN_set_word(t1, 10))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 3))
|
||||
goto err;
|
||||
/*
|
||||
* BN_set_word(t3,7); just have to miss out on these ones :-(
|
||||
*/
|
||||
g = 5;
|
||||
} else {
|
||||
/*
|
||||
* in the general case, don't worry if 'generator' is a generator or
|
||||
* not: since we are using safe primes, it will generate either an
|
||||
* order-q or an order-2q group, which both is OK
|
||||
*/
|
||||
if (!BN_set_word(t1, 2))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 1))
|
||||
goto err;
|
||||
g = generator;
|
||||
}
|
||||
|
||||
if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb))
|
||||
goto err;
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
goto err;
|
||||
if (!BN_set_word(ret->g, g))
|
||||
goto err;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
DHerr(DH_F_DH_BUILTIN_GENPARAMS, ERR_R_BN_LIB);
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
/* crypto/dh/dh_check.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
|
||||
/*-
|
||||
* Check that p is a safe prime and
|
||||
* if g is 2, 3 or 5, check that is is a suitable generator
|
||||
* where
|
||||
* for 2, p mod 24 == 11
|
||||
* for 3, p mod 12 == 5
|
||||
* for 5, p mod 10 == 3 or 7
|
||||
* should hold.
|
||||
*/
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
int DH_check(const DH *dh, int *ret)
|
||||
{
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
BN_ULONG l;
|
||||
BIGNUM *q = NULL;
|
||||
|
||||
*ret = 0;
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
q = BN_new();
|
||||
if (q == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_is_word(dh->g, DH_GENERATOR_2)) {
|
||||
l = BN_mod_word(dh->p, 24);
|
||||
if (l != 11)
|
||||
*ret |= DH_NOT_SUITABLE_GENERATOR;
|
||||
}
|
||||
# if 0
|
||||
else if (BN_is_word(dh->g, DH_GENERATOR_3)) {
|
||||
l = BN_mod_word(dh->p, 12);
|
||||
if (l != 5)
|
||||
*ret |= DH_NOT_SUITABLE_GENERATOR;
|
||||
}
|
||||
# endif
|
||||
else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
|
||||
l = BN_mod_word(dh->p, 10);
|
||||
if ((l != 3) && (l != 7))
|
||||
*ret |= DH_NOT_SUITABLE_GENERATOR;
|
||||
} else
|
||||
*ret |= DH_UNABLE_TO_CHECK_GENERATOR;
|
||||
|
||||
if (!BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL))
|
||||
*ret |= DH_CHECK_P_NOT_PRIME;
|
||||
else {
|
||||
if (!BN_rshift1(q, dh->p))
|
||||
goto err;
|
||||
if (!BN_is_prime_ex(q, BN_prime_checks, ctx, NULL))
|
||||
*ret |= DH_CHECK_P_NOT_SAFE_PRIME;
|
||||
}
|
||||
ok = 1;
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
if (q != NULL)
|
||||
BN_free(q);
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
|
||||
{
|
||||
int ok = 0;
|
||||
BIGNUM *q = NULL;
|
||||
|
||||
*ret = 0;
|
||||
q = BN_new();
|
||||
if (q == NULL)
|
||||
goto err;
|
||||
BN_set_word(q, 1);
|
||||
if (BN_cmp(pub_key, q) <= 0)
|
||||
*ret |= DH_CHECK_PUBKEY_TOO_SMALL;
|
||||
BN_copy(q, dh->p);
|
||||
BN_sub_word(q, 1);
|
||||
if (BN_cmp(pub_key, q) >= 0)
|
||||
*ret |= DH_CHECK_PUBKEY_TOO_LARGE;
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
if (q != NULL)
|
||||
BN_free(q);
|
||||
return (ok);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,204 @@
|
||||
/* crypto/dh/dh_gen.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
/*
|
||||
* NB: These functions have been upgraded - the previous prototypes are in
|
||||
* dh_depr.c as wrappers to these ones. - Geoff
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb);
|
||||
|
||||
int DH_generate_parameters_ex(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
if (ret->meth->generate_params)
|
||||
return ret->meth->generate_params(ret, prime_len, generator, cb);
|
||||
return dh_builtin_genparams(ret, prime_len, generator, cb);
|
||||
}
|
||||
|
||||
/*-
|
||||
* We generate DH parameters as follows
|
||||
* find a prime q which is prime_len/2 bits long.
|
||||
* p=(2*q)+1 or (p-1)/2 = q
|
||||
* For this case, g is a generator if
|
||||
* g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
|
||||
* Since the factors of p-1 are q and 2, we just need to check
|
||||
* g^2 mod p != 1 and g^q mod p != 1.
|
||||
*
|
||||
* Having said all that,
|
||||
* there is another special case method for the generators 2, 3 and 5.
|
||||
* for 2, p mod 24 == 11
|
||||
* for 3, p mod 12 == 5 <<<<< does not work for safe primes.
|
||||
* for 5, p mod 10 == 3 or 7
|
||||
*
|
||||
* Thanks to Phil Karn <karn@qualcomm.com> for the pointers about the
|
||||
* special generators and for answering some of my questions.
|
||||
*
|
||||
* I've implemented the second simple method :-).
|
||||
* Since DH should be using a safe prime (both p and q are prime),
|
||||
* this generator function can take a very very long time to run.
|
||||
*/
|
||||
/*
|
||||
* Actually there is no reason to insist that 'generator' be a generator.
|
||||
* It's just as OK (and in some sense better) to use a generator of the
|
||||
* order-q subgroup.
|
||||
*/
|
||||
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *t1, *t2;
|
||||
int g, ok = -1;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_DH_BUILTIN_GENPARAMS, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FIPS_mode() && (prime_len < OPENSSL_DH_FIPS_MIN_MODULUS_BITS)) {
|
||||
DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
t2 = BN_CTX_get(ctx);
|
||||
if (t1 == NULL || t2 == NULL)
|
||||
goto err;
|
||||
|
||||
/* Make sure 'ret' has the necessary elements */
|
||||
if (!ret->p && ((ret->p = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!ret->g && ((ret->g = BN_new()) == NULL))
|
||||
goto err;
|
||||
|
||||
if (generator <= 1) {
|
||||
DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
|
||||
goto err;
|
||||
}
|
||||
if (generator == DH_GENERATOR_2) {
|
||||
if (!BN_set_word(t1, 24))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 11))
|
||||
goto err;
|
||||
g = 2;
|
||||
}
|
||||
# if 0 /* does not work for safe primes */
|
||||
else if (generator == DH_GENERATOR_3) {
|
||||
if (!BN_set_word(t1, 12))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 5))
|
||||
goto err;
|
||||
g = 3;
|
||||
}
|
||||
# endif
|
||||
else if (generator == DH_GENERATOR_5) {
|
||||
if (!BN_set_word(t1, 10))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 3))
|
||||
goto err;
|
||||
/*
|
||||
* BN_set_word(t3,7); just have to miss out on these ones :-(
|
||||
*/
|
||||
g = 5;
|
||||
} else {
|
||||
/*
|
||||
* in the general case, don't worry if 'generator' is a generator or
|
||||
* not: since we are using safe primes, it will generate either an
|
||||
* order-q or an order-2q group, which both is OK
|
||||
*/
|
||||
if (!BN_set_word(t1, 2))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 1))
|
||||
goto err;
|
||||
g = generator;
|
||||
}
|
||||
|
||||
if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb))
|
||||
goto err;
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
goto err;
|
||||
if (!BN_set_word(ret->g, g))
|
||||
goto err;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
DHerr(DH_F_DH_BUILTIN_GENPARAMS, ERR_R_BN_LIB);
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,267 @@
|
||||
/* crypto/dh/dh_key.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bn.h>
|
||||
#ifndef OPENSSL_NO_RAND
|
||||
# include <openssl/rand.h>
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DH
|
||||
# include <openssl/dh.h>
|
||||
# include <openssl/fips.h>
|
||||
|
||||
# ifdef OPENSSL_FIPS
|
||||
|
||||
static int generate_key(DH *dh);
|
||||
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
|
||||
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
|
||||
const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
||||
static int dh_init(DH *dh);
|
||||
static int dh_finish(DH *dh);
|
||||
|
||||
int DH_generate_key(DH *dh)
|
||||
{
|
||||
return dh->meth->generate_key(dh);
|
||||
}
|
||||
|
||||
int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
||||
{
|
||||
return dh->meth->compute_key(key, pub_key, dh);
|
||||
}
|
||||
|
||||
static const DH_METHOD dh_ossl = {
|
||||
"OpenSSL DH Method",
|
||||
generate_key,
|
||||
compute_key,
|
||||
dh_bn_mod_exp,
|
||||
dh_init,
|
||||
dh_finish,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
|
||||
const DH_METHOD *DH_OpenSSL(void)
|
||||
{
|
||||
return &dh_ossl;
|
||||
}
|
||||
|
||||
static int generate_key(DH *dh)
|
||||
{
|
||||
int ok = 0;
|
||||
int generate_new_key = 0;
|
||||
unsigned l;
|
||||
BN_CTX *ctx;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
BIGNUM *pub_key = NULL, *priv_key = NULL;
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(dh->p) < OPENSSL_DH_FIPS_MIN_MODULUS_BITS)) {
|
||||
DHerr(DH_F_GENERATE_KEY, DH_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
if (dh->priv_key == NULL) {
|
||||
priv_key = BN_new();
|
||||
if (priv_key == NULL)
|
||||
goto err;
|
||||
generate_new_key = 1;
|
||||
} else
|
||||
priv_key = dh->priv_key;
|
||||
|
||||
if (dh->pub_key == NULL) {
|
||||
pub_key = BN_new();
|
||||
if (pub_key == NULL)
|
||||
goto err;
|
||||
} else
|
||||
pub_key = dh->pub_key;
|
||||
|
||||
if (dh->flags & DH_FLAG_CACHE_MONT_P) {
|
||||
mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dh->method_mont_p,
|
||||
CRYPTO_LOCK_DH, dh->p, ctx);
|
||||
if (!mont)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (generate_new_key) {
|
||||
l = dh->length ? dh->length : BN_num_bits(dh->p) - 1; /* secret
|
||||
* exponent
|
||||
* length */
|
||||
if (!BN_rand(priv_key, l, 0, 0))
|
||||
goto err;
|
||||
}
|
||||
|
||||
{
|
||||
BIGNUM local_prk;
|
||||
BIGNUM *prk;
|
||||
|
||||
if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) {
|
||||
BN_init(&local_prk);
|
||||
prk = &local_prk;
|
||||
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
prk = priv_key;
|
||||
|
||||
if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont))
|
||||
goto err;
|
||||
}
|
||||
|
||||
dh->pub_key = pub_key;
|
||||
dh->priv_key = priv_key;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok != 1)
|
||||
DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
|
||||
|
||||
if ((pub_key != NULL) && (dh->pub_key == NULL))
|
||||
BN_free(pub_key);
|
||||
if ((priv_key != NULL) && (dh->priv_key == NULL))
|
||||
BN_free(priv_key);
|
||||
BN_CTX_free(ctx);
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
||||
{
|
||||
BN_CTX *ctx;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
BIGNUM *tmp;
|
||||
int ret = -1;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
|
||||
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
|
||||
DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(dh->p) < OPENSSL_DH_FIPS_MIN_MODULUS_BITS)) {
|
||||
DHerr(DH_F_COMPUTE_KEY, DH_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dh->priv_key == NULL) {
|
||||
DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dh->flags & DH_FLAG_CACHE_MONT_P) {
|
||||
mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dh->method_mont_p,
|
||||
CRYPTO_LOCK_DH, dh->p, ctx);
|
||||
if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) {
|
||||
/* XXX */
|
||||
BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
|
||||
}
|
||||
if (!mont)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!dh->
|
||||
meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
|
||||
DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = BN_bn2bin(tmp, key);
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
|
||||
const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
|
||||
{
|
||||
/*
|
||||
* If a is only one word long and constant time is false, use the faster
|
||||
* exponenentiation function.
|
||||
*/
|
||||
if (a->top == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0)) {
|
||||
BN_ULONG A = a->d[0];
|
||||
return BN_mod_exp_mont_word(r, A, p, m, ctx, m_ctx);
|
||||
} else
|
||||
return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
|
||||
}
|
||||
|
||||
static int dh_init(DH *dh)
|
||||
{
|
||||
FIPS_selftest_check();
|
||||
dh->flags |= DH_FLAG_CACHE_MONT_P;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int dh_finish(DH *dh)
|
||||
{
|
||||
if (dh->method_mont_p)
|
||||
BN_MONT_CTX_free((BN_MONT_CTX *)dh->method_mont_p);
|
||||
return (1);
|
||||
}
|
||||
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/* fips_dh_lib.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2007.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
/*
|
||||
* Minimal FIPS versions of FIPS_dh_new() and FIPS_dh_free(): to reduce
|
||||
* external dependencies.
|
||||
*/
|
||||
|
||||
DH *FIPS_dh_new(void)
|
||||
{
|
||||
DH *ret;
|
||||
ret = OPENSSL_malloc(sizeof(DH));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
memset(ret, 0, sizeof(DH));
|
||||
ret->meth = DH_OpenSSL();
|
||||
if (ret->meth->init)
|
||||
ret->meth->init(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FIPS_dh_free(DH *r)
|
||||
{
|
||||
if (!r)
|
||||
return;
|
||||
if (r->meth->finish)
|
||||
r->meth->finish(r);
|
||||
if (r->p != NULL)
|
||||
BN_clear_free(r->p);
|
||||
if (r->g != NULL)
|
||||
BN_clear_free(r->g);
|
||||
if (r->q != NULL)
|
||||
BN_clear_free(r->q);
|
||||
if (r->j != NULL)
|
||||
BN_clear_free(r->j);
|
||||
if (r->seed)
|
||||
OPENSSL_free(r->seed);
|
||||
if (r->counter != NULL)
|
||||
BN_clear_free(r->counter);
|
||||
if (r->pub_key != NULL)
|
||||
BN_clear_free(r->pub_key);
|
||||
if (r->priv_key != NULL)
|
||||
BN_clear_free(r->priv_key);
|
||||
OPENSSL_free(r);
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
/* crypto/dsa/dsa_gen.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#undef GENUINE_DSA
|
||||
|
||||
#ifdef GENUINE_DSA
|
||||
/*
|
||||
* Parameter generation follows the original release of FIPS PUB 186,
|
||||
* Appendix 2.2 (i.e. use SHA as defined in FIPS PUB 180)
|
||||
*/
|
||||
# define HASH EVP_sha()
|
||||
#else
|
||||
/*
|
||||
* Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186,
|
||||
* also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB
|
||||
* 180-1)
|
||||
*/
|
||||
# define HASH EVP_sha1()
|
||||
#endif
|
||||
|
||||
#include <openssl/opensslconf.h> /* To see if OPENSSL_NO_SHA is defined */
|
||||
|
||||
#ifndef OPENSSL_NO_SHA
|
||||
|
||||
# include <stdio.h>
|
||||
# include <time.h>
|
||||
# include <string.h>
|
||||
# include <openssl/evp.h>
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/dsa.h>
|
||||
# include <openssl/rand.h>
|
||||
# include <openssl/sha.h>
|
||||
# include <openssl/err.h>
|
||||
|
||||
# ifdef OPENSSL_FIPS
|
||||
|
||||
static int dsa_builtin_paramgen(DSA *ret, int bits,
|
||||
unsigned char *seed_in, int seed_len,
|
||||
int *counter_ret, unsigned long *h_ret,
|
||||
BN_GENCB *cb);
|
||||
|
||||
int DSA_generate_parameters_ex(DSA *ret, int bits,
|
||||
unsigned char *seed_in, int seed_len,
|
||||
int *counter_ret, unsigned long *h_ret,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
if (ret->meth->dsa_paramgen)
|
||||
return ret->meth->dsa_paramgen(ret, bits, seed_in, seed_len,
|
||||
counter_ret, h_ret, cb);
|
||||
return dsa_builtin_paramgen(ret, bits, seed_in, seed_len,
|
||||
counter_ret, h_ret, cb);
|
||||
}
|
||||
|
||||
static int dsa_builtin_paramgen(DSA *ret, int bits,
|
||||
unsigned char *seed_in, int seed_len,
|
||||
int *counter_ret, unsigned long *h_ret,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
int ok = 0;
|
||||
unsigned char seed[SHA_DIGEST_LENGTH];
|
||||
unsigned char md[SHA_DIGEST_LENGTH];
|
||||
unsigned char buf[SHA_DIGEST_LENGTH], buf2[SHA_DIGEST_LENGTH];
|
||||
BIGNUM *r0, *W, *X, *c, *test;
|
||||
BIGNUM *g = NULL, *q = NULL, *p = NULL;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
int k, n = 0, i, b, m = 0;
|
||||
int counter = 0;
|
||||
int r = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
unsigned int h = 2;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_DSA_BUILTIN_PARAMGEN, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FIPS_mode() && (bits < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (bits < 512)
|
||||
bits = 512;
|
||||
bits = (bits + 63) / 64 * 64;
|
||||
|
||||
/*
|
||||
* NB: seed_len == 0 is special case: copy generated seed to seed_in if
|
||||
* it is not NULL.
|
||||
*/
|
||||
if (seed_len && (seed_len < 20))
|
||||
seed_in = NULL; /* seed buffer too small -- ignore */
|
||||
if (seed_len > 20)
|
||||
seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger
|
||||
* SEED, but our internal buffers are
|
||||
* restricted to 160 bits */
|
||||
if ((seed_in != NULL) && (seed_len == 20)) {
|
||||
memcpy(seed, seed_in, seed_len);
|
||||
/* set seed_in to NULL to avoid it being copied back */
|
||||
seed_in = NULL;
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if ((mont = BN_MONT_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
r0 = BN_CTX_get(ctx);
|
||||
g = BN_CTX_get(ctx);
|
||||
W = BN_CTX_get(ctx);
|
||||
q = BN_CTX_get(ctx);
|
||||
X = BN_CTX_get(ctx);
|
||||
c = BN_CTX_get(ctx);
|
||||
p = BN_CTX_get(ctx);
|
||||
test = BN_CTX_get(ctx);
|
||||
|
||||
if (!BN_lshift(test, BN_value_one(), bits - 1))
|
||||
goto err;
|
||||
|
||||
for (;;) {
|
||||
for (;;) { /* find q */
|
||||
int seed_is_random;
|
||||
|
||||
/* step 1 */
|
||||
if (!BN_GENCB_call(cb, 0, m++))
|
||||
goto err;
|
||||
|
||||
if (!seed_len) {
|
||||
RAND_pseudo_bytes(seed, SHA_DIGEST_LENGTH);
|
||||
seed_is_random = 1;
|
||||
} else {
|
||||
seed_is_random = 0;
|
||||
seed_len = 0; /* use random seed if 'seed_in' turns out to
|
||||
* be bad */
|
||||
}
|
||||
memcpy(buf, seed, SHA_DIGEST_LENGTH);
|
||||
memcpy(buf2, seed, SHA_DIGEST_LENGTH);
|
||||
/* precompute "SEED + 1" for step 7: */
|
||||
for (i = SHA_DIGEST_LENGTH - 1; i >= 0; i--) {
|
||||
buf[i]++;
|
||||
if (buf[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* step 2 */
|
||||
EVP_Digest(seed, SHA_DIGEST_LENGTH, md, NULL, HASH, NULL);
|
||||
EVP_Digest(buf, SHA_DIGEST_LENGTH, buf2, NULL, HASH, NULL);
|
||||
for (i = 0; i < SHA_DIGEST_LENGTH; i++)
|
||||
md[i] ^= buf2[i];
|
||||
|
||||
/* step 3 */
|
||||
md[0] |= 0x80;
|
||||
md[SHA_DIGEST_LENGTH - 1] |= 0x01;
|
||||
if (!BN_bin2bn(md, SHA_DIGEST_LENGTH, q))
|
||||
goto err;
|
||||
|
||||
/* step 4 */
|
||||
r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
|
||||
seed_is_random, cb);
|
||||
if (r > 0)
|
||||
break;
|
||||
if (r != 0)
|
||||
goto err;
|
||||
|
||||
/* do a callback call */
|
||||
/* step 5 */
|
||||
}
|
||||
|
||||
if (!BN_GENCB_call(cb, 2, 0))
|
||||
goto err;
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
goto err;
|
||||
|
||||
/* step 6 */
|
||||
counter = 0;
|
||||
/* "offset = 2" */
|
||||
|
||||
n = (bits - 1) / 160;
|
||||
b = (bits - 1) - n * 160;
|
||||
|
||||
for (;;) {
|
||||
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
|
||||
goto err;
|
||||
|
||||
/* step 7 */
|
||||
BN_zero(W);
|
||||
/* now 'buf' contains "SEED + offset - 1" */
|
||||
for (k = 0; k <= n; k++) {
|
||||
/*
|
||||
* obtain "SEED + offset + k" by incrementing:
|
||||
*/
|
||||
for (i = SHA_DIGEST_LENGTH - 1; i >= 0; i--) {
|
||||
buf[i]++;
|
||||
if (buf[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
EVP_Digest(buf, SHA_DIGEST_LENGTH, md, NULL, HASH, NULL);
|
||||
|
||||
/* step 8 */
|
||||
if (!BN_bin2bn(md, SHA_DIGEST_LENGTH, r0))
|
||||
goto err;
|
||||
if (!BN_lshift(r0, r0, 160 * k))
|
||||
goto err;
|
||||
if (!BN_add(W, W, r0))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* more of step 8 */
|
||||
if (!BN_mask_bits(W, bits - 1))
|
||||
goto err;
|
||||
if (!BN_copy(X, W))
|
||||
goto err;
|
||||
if (!BN_add(X, X, test))
|
||||
goto err;
|
||||
|
||||
/* step 9 */
|
||||
if (!BN_lshift1(r0, q))
|
||||
goto err;
|
||||
if (!BN_mod(c, X, r0, ctx))
|
||||
goto err;
|
||||
if (!BN_sub(r0, c, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_sub(p, X, r0))
|
||||
goto err;
|
||||
|
||||
/* step 10 */
|
||||
if (BN_cmp(p, test) >= 0) {
|
||||
/* step 11 */
|
||||
r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
|
||||
if (r > 0)
|
||||
goto end; /* found it */
|
||||
if (r != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 13 */
|
||||
counter++;
|
||||
/* "offset = offset + n + 1" */
|
||||
|
||||
/* step 14 */
|
||||
if (counter >= 4096)
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
if (!BN_GENCB_call(cb, 2, 1))
|
||||
goto err;
|
||||
|
||||
/* We now need to generate g */
|
||||
/* Set r0=(p-1)/q */
|
||||
if (!BN_sub(test, p, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_div(r0, NULL, test, q, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_set_word(test, h))
|
||||
goto err;
|
||||
if (!BN_MONT_CTX_set(mont, p, ctx))
|
||||
goto err;
|
||||
|
||||
for (;;) {
|
||||
/* g=test^r0%p */
|
||||
if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
|
||||
goto err;
|
||||
if (!BN_is_one(g))
|
||||
break;
|
||||
if (!BN_add(test, test, BN_value_one()))
|
||||
goto err;
|
||||
h++;
|
||||
}
|
||||
|
||||
if (!BN_GENCB_call(cb, 3, 1))
|
||||
goto err;
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok) {
|
||||
if (ret->p)
|
||||
BN_free(ret->p);
|
||||
if (ret->q)
|
||||
BN_free(ret->q);
|
||||
if (ret->g)
|
||||
BN_free(ret->g);
|
||||
ret->p = BN_dup(p);
|
||||
ret->q = BN_dup(q);
|
||||
ret->g = BN_dup(g);
|
||||
if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
|
||||
ok = 0;
|
||||
goto err;
|
||||
}
|
||||
if (seed_in != NULL)
|
||||
memcpy(seed_in, seed, 20);
|
||||
if (counter_ret != NULL)
|
||||
*counter_ret = counter;
|
||||
if (h_ret != NULL)
|
||||
*h_ret = h;
|
||||
}
|
||||
if (ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (mont != NULL)
|
||||
BN_MONT_CTX_free(mont);
|
||||
return ok;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,169 @@
|
||||
/* crypto/dsa/dsa_key.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#ifndef OPENSSL_NO_SHA
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/dsa.h>
|
||||
# include <openssl/rand.h>
|
||||
# include <openssl/err.h>
|
||||
# include <openssl/evp.h>
|
||||
# include <openssl/fips.h>
|
||||
# include "fips_locl.h"
|
||||
|
||||
# ifdef OPENSSL_FIPS
|
||||
|
||||
static int fips_dsa_pairwise_fail = 0;
|
||||
|
||||
void FIPS_corrupt_dsa_keygen(void)
|
||||
{
|
||||
fips_dsa_pairwise_fail = 1;
|
||||
}
|
||||
|
||||
static int dsa_builtin_keygen(DSA *dsa);
|
||||
|
||||
static int fips_check_dsa(DSA *dsa)
|
||||
{
|
||||
EVP_PKEY pk;
|
||||
unsigned char tbs[] = "DSA Pairwise Check Data";
|
||||
pk.type = EVP_PKEY_DSA;
|
||||
pk.pkey.dsa = dsa;
|
||||
|
||||
if (!fips_pkey_signature_test(&pk, tbs, -1, NULL, 0, EVP_dss1(), 0, NULL)) {
|
||||
FIPSerr(FIPS_F_FIPS_CHECK_DSA, FIPS_R_PAIRWISE_TEST_FAILED);
|
||||
fips_set_selftest_fail();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DSA_generate_key(DSA *dsa)
|
||||
{
|
||||
if (dsa->meth->dsa_keygen)
|
||||
return dsa->meth->dsa_keygen(dsa);
|
||||
return dsa_builtin_keygen(dsa);
|
||||
}
|
||||
|
||||
static int dsa_builtin_keygen(DSA *dsa)
|
||||
{
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
BIGNUM *pub_key = NULL, *priv_key = NULL;
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
DSAerr(DSA_F_DSA_BUILTIN_KEYGEN, DSA_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if (dsa->priv_key == NULL) {
|
||||
if ((priv_key = BN_new()) == NULL)
|
||||
goto err;
|
||||
} else
|
||||
priv_key = dsa->priv_key;
|
||||
|
||||
do
|
||||
if (!BN_rand_range(priv_key, dsa->q))
|
||||
goto err;
|
||||
while (BN_is_zero(priv_key)) ;
|
||||
|
||||
if (dsa->pub_key == NULL) {
|
||||
if ((pub_key = BN_new()) == NULL)
|
||||
goto err;
|
||||
} else
|
||||
pub_key = dsa->pub_key;
|
||||
|
||||
{
|
||||
BIGNUM local_prk;
|
||||
BIGNUM *prk;
|
||||
|
||||
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) {
|
||||
BN_init(&local_prk);
|
||||
prk = &local_prk;
|
||||
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
prk = priv_key;
|
||||
|
||||
if (!BN_mod_exp(pub_key, dsa->g, prk, dsa->p, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
dsa->priv_key = priv_key;
|
||||
dsa->pub_key = pub_key;
|
||||
if (fips_dsa_pairwise_fail)
|
||||
BN_add_word(dsa->pub_key, 1);
|
||||
if (!fips_check_dsa(dsa))
|
||||
goto err;
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
if ((pub_key != NULL) && (dsa->pub_key == NULL))
|
||||
BN_free(pub_key);
|
||||
if ((priv_key != NULL) && (dsa->priv_key == NULL))
|
||||
BN_free(priv_key);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
return (ok);
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
/* fips_dsa_lib.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2007.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/*
|
||||
* Minimal FIPS versions of FIPS_dsa_new() and FIPS_dsa_free: to reduce
|
||||
* external dependencies.
|
||||
*/
|
||||
|
||||
DSA *FIPS_dsa_new(void)
|
||||
{
|
||||
DSA *ret;
|
||||
ret = OPENSSL_malloc(sizeof(DSA));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
memset(ret, 0, sizeof(DSA));
|
||||
ret->meth = DSA_OpenSSL();
|
||||
if (ret->meth->init)
|
||||
ret->meth->init(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FIPS_dsa_free(DSA *r)
|
||||
{
|
||||
if (!r)
|
||||
return;
|
||||
if (r->meth->finish)
|
||||
r->meth->finish(r);
|
||||
if (r->p != NULL)
|
||||
BN_clear_free(r->p);
|
||||
if (r->q != NULL)
|
||||
BN_clear_free(r->q);
|
||||
if (r->g != NULL)
|
||||
BN_clear_free(r->g);
|
||||
if (r->pub_key != NULL)
|
||||
BN_clear_free(r->pub_key);
|
||||
if (r->priv_key != NULL)
|
||||
BN_clear_free(r->priv_key);
|
||||
if (r->kinv != NULL)
|
||||
BN_clear_free(r->kinv);
|
||||
if (r->r != NULL)
|
||||
BN_clear_free(r->r);
|
||||
OPENSSL_free(r);
|
||||
}
|
||||
@@ -0,0 +1,452 @@
|
||||
/* crypto/dsa/dsa_ossl.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
/* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/err.h>
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
# include <openssl/engine.h>
|
||||
#endif
|
||||
#include <openssl/fips.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, FIPS_DSA_SIZE_T dlen,
|
||||
DSA *dsa);
|
||||
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
|
||||
BIGNUM **rp);
|
||||
static int dsa_do_verify(const unsigned char *dgst, FIPS_DSA_SIZE_T dgst_len,
|
||||
DSA_SIG *sig, DSA *dsa);
|
||||
static int dsa_init(DSA *dsa);
|
||||
static int dsa_finish(DSA *dsa);
|
||||
static int dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
|
||||
BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
|
||||
BN_MONT_CTX *in_mont);
|
||||
static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
||||
|
||||
static const DSA_METHOD openssl_dsa_meth = {
|
||||
"OpenSSL FIPS DSA method",
|
||||
dsa_do_sign,
|
||||
dsa_sign_setup,
|
||||
dsa_do_verify,
|
||||
dsa_mod_exp,
|
||||
dsa_bn_mod_exp,
|
||||
dsa_init,
|
||||
dsa_finish,
|
||||
DSA_FLAG_FIPS_METHOD,
|
||||
NULL
|
||||
};
|
||||
|
||||
# if 0
|
||||
int FIPS_dsa_check(struct dsa_st *dsa)
|
||||
{
|
||||
if (dsa->meth != &openssl_dsa_meth
|
||||
|| dsa->meth->dsa_do_sign != dsa_do_sign
|
||||
|| dsa->meth->dsa_sign_setup != dsa_sign_setup
|
||||
|| dsa->meth->dsa_mod_exp != dsa_mod_exp
|
||||
|| dsa->meth->bn_mod_exp != dsa_bn_mod_exp
|
||||
|| dsa->meth->init != dsa_init || dsa->meth->finish != dsa_finish) {
|
||||
FIPSerr(FIPS_F_FIPS_DSA_CHECK, FIPS_R_NON_FIPS_METHOD);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
# endif
|
||||
|
||||
const DSA_METHOD *DSA_OpenSSL(void)
|
||||
{
|
||||
return &openssl_dsa_meth;
|
||||
}
|
||||
|
||||
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, FIPS_DSA_SIZE_T dlen,
|
||||
DSA *dsa)
|
||||
{
|
||||
BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
|
||||
BIGNUM m;
|
||||
BIGNUM xr;
|
||||
BN_CTX *ctx = NULL;
|
||||
int i, reason = ERR_R_BN_LIB;
|
||||
DSA_SIG *ret = NULL;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_DSA_DO_SIGN, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BN_init(&m);
|
||||
BN_init(&xr);
|
||||
|
||||
if (!dsa->p || !dsa->q || !dsa->g) {
|
||||
reason = DSA_R_MISSING_PARAMETERS;
|
||||
goto err;
|
||||
}
|
||||
|
||||
s = BN_new();
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
|
||||
i = BN_num_bytes(dsa->q); /* should be 20 */
|
||||
if ((dlen > i) || (dlen > 50)) {
|
||||
reason = DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
if (!dsa->meth->dsa_sign_setup(dsa, ctx, &kinv, &r))
|
||||
goto err;
|
||||
|
||||
if (BN_bin2bn(dgst, dlen, &m) == NULL)
|
||||
goto err;
|
||||
|
||||
/* Compute s = inv(k) (m + xr) mod q */
|
||||
if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx))
|
||||
goto err; /* s = xr */
|
||||
if (!BN_add(s, &xr, &m))
|
||||
goto err; /* s = m + xr */
|
||||
if (BN_cmp(s, dsa->q) > 0)
|
||||
BN_sub(s, s, dsa->q);
|
||||
if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
ret = DSA_SIG_new();
|
||||
if (ret == NULL)
|
||||
goto err;
|
||||
ret->r = r;
|
||||
ret->s = s;
|
||||
|
||||
err:
|
||||
if (!ret) {
|
||||
DSAerr(DSA_F_DSA_DO_SIGN, reason);
|
||||
BN_free(r);
|
||||
BN_free(s);
|
||||
}
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
BN_clear_free(&m);
|
||||
BN_clear_free(&xr);
|
||||
if (kinv != NULL) /* dsa->kinv is NULL now if we used it */
|
||||
BN_clear_free(kinv);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
|
||||
BIGNUM **rp)
|
||||
{
|
||||
BN_CTX *ctx;
|
||||
BIGNUM k, kq, *K, *kinv = NULL, *r = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!dsa->p || !dsa->q || !dsa->g) {
|
||||
DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_init(&k);
|
||||
BN_init(&kq);
|
||||
|
||||
if (ctx_in == NULL) {
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
} else
|
||||
ctx = ctx_in;
|
||||
|
||||
if ((r = BN_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
/* Get random k */
|
||||
do
|
||||
if (!BN_rand_range(&k, dsa->q))
|
||||
goto err;
|
||||
while (BN_is_zero(&k)) ;
|
||||
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) {
|
||||
BN_set_flags(&k, BN_FLG_CONSTTIME);
|
||||
}
|
||||
|
||||
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
|
||||
if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
|
||||
CRYPTO_LOCK_DSA, dsa->p, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Compute r = (g^k mod p) mod q */
|
||||
|
||||
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) {
|
||||
if (!BN_copy(&kq, &k))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* We do not want timing information to leak the length of k, so we
|
||||
* compute g^k using an equivalent exponent of fixed length. (This
|
||||
* is a kludge that we need because the BN_mod_exp_mont() does not
|
||||
* let us specify the desired timing behaviour.)
|
||||
*/
|
||||
|
||||
if (!BN_add(&kq, &kq, dsa->q))
|
||||
goto err;
|
||||
if (BN_num_bits(&kq) <= BN_num_bits(dsa->q)) {
|
||||
if (!BN_add(&kq, &kq, dsa->q))
|
||||
goto err;
|
||||
}
|
||||
|
||||
K = &kq;
|
||||
} else {
|
||||
K = &k;
|
||||
}
|
||||
if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, K, dsa->p, ctx,
|
||||
(BN_MONT_CTX *)dsa->method_mont_p))
|
||||
goto err;
|
||||
if (!BN_mod(r, r, dsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* Compute part of 's = inv(k) (m + xr) mod q' */
|
||||
if ((kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (*kinvp != NULL)
|
||||
BN_clear_free(*kinvp);
|
||||
*kinvp = kinv;
|
||||
kinv = NULL;
|
||||
if (*rp != NULL)
|
||||
BN_clear_free(*rp);
|
||||
*rp = r;
|
||||
ret = 1;
|
||||
err:
|
||||
if (!ret) {
|
||||
DSAerr(DSA_F_DSA_SIGN_SETUP, ERR_R_BN_LIB);
|
||||
if (kinv != NULL)
|
||||
BN_clear_free(kinv);
|
||||
if (r != NULL)
|
||||
BN_clear_free(r);
|
||||
}
|
||||
if (ctx_in == NULL)
|
||||
BN_CTX_free(ctx);
|
||||
if (kinv != NULL)
|
||||
BN_clear_free(kinv);
|
||||
BN_clear_free(&k);
|
||||
BN_clear_free(&kq);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int dsa_do_verify(const unsigned char *dgst, FIPS_DSA_SIZE_T dgst_len,
|
||||
DSA_SIG *sig, DSA *dsa)
|
||||
{
|
||||
BN_CTX *ctx;
|
||||
BIGNUM u1, u2, t1;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (!dsa->p || !dsa->q || !dsa->g) {
|
||||
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MISSING_PARAMETERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_DSA_DO_VERIFY, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_num_bits(dsa->q) != 160) {
|
||||
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_BAD_Q_VALUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
|
||||
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MODULUS_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
BN_init(&u1);
|
||||
BN_init(&u2);
|
||||
BN_init(&t1);
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate W = inv(S) mod Q save W in u2
|
||||
*/
|
||||
if ((BN_mod_inverse(&u2, sig->s, dsa->q, ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
/* save M in u1 */
|
||||
if (BN_bin2bn(dgst, dgst_len, &u1) == NULL)
|
||||
goto err;
|
||||
|
||||
/* u1 = M * w mod q */
|
||||
if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* u2 = r * w mod q */
|
||||
if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
|
||||
mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
|
||||
CRYPTO_LOCK_DSA, dsa->p, ctx);
|
||||
if (!mont)
|
||||
goto err;
|
||||
}
|
||||
# if 0
|
||||
{
|
||||
BIGNUM t2;
|
||||
|
||||
BN_init(&t2);
|
||||
/* v = ( g^u1 * y^u2 mod p ) mod q */
|
||||
/* let t1 = g ^ u1 mod p */
|
||||
if (!BN_mod_exp_mont(&t1, dsa->g, &u1, dsa->p, ctx, mont))
|
||||
goto err;
|
||||
/* let t2 = y ^ u2 mod p */
|
||||
if (!BN_mod_exp_mont(&t2, dsa->pub_key, &u2, dsa->p, ctx, mont))
|
||||
goto err;
|
||||
/* let u1 = t1 * t2 mod p */
|
||||
if (!BN_mod_mul(&u1, &t1, &t2, dsa->p, ctx))
|
||||
goto err_bn;
|
||||
BN_free(&t2);
|
||||
}
|
||||
/* let u1 = u1 mod q */
|
||||
if (!BN_mod(&u1, &u1, dsa->q, ctx))
|
||||
goto err;
|
||||
# else
|
||||
{
|
||||
if (!dsa->meth->dsa_mod_exp(dsa, &t1, dsa->g, &u1, dsa->pub_key, &u2,
|
||||
dsa->p, ctx, mont))
|
||||
goto err;
|
||||
/* BN_copy(&u1,&t1); */
|
||||
/* let u1 = u1 mod q */
|
||||
if (!BN_mod(&u1, &t1, dsa->q, ctx))
|
||||
goto err;
|
||||
}
|
||||
# endif
|
||||
/*
|
||||
* V is now in u1. If the signature is correct, it will be equal to R.
|
||||
*/
|
||||
ret = (BN_ucmp(&u1, sig->r) == 0);
|
||||
|
||||
err:
|
||||
if (ret != 1)
|
||||
DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_BN_LIB);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
BN_free(&u1);
|
||||
BN_free(&u2);
|
||||
BN_free(&t1);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int dsa_init(DSA *dsa)
|
||||
{
|
||||
FIPS_selftest_check();
|
||||
dsa->flags |= DSA_FLAG_CACHE_MONT_P;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int dsa_finish(DSA *dsa)
|
||||
{
|
||||
if (dsa->method_mont_p)
|
||||
BN_MONT_CTX_free((BN_MONT_CTX *)dsa->method_mont_p);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
|
||||
BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
|
||||
BN_MONT_CTX *in_mont)
|
||||
{
|
||||
return BN_mod_exp2_mont(rr, a1, p1, a2, p2, m, ctx, in_mont);
|
||||
}
|
||||
|
||||
static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
|
||||
{
|
||||
return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
|
||||
}
|
||||
|
||||
#else /* ndef OPENSSL_FIPS */
|
||||
|
||||
static void *dummy = &dummy;
|
||||
|
||||
#endif /* ndef OPENSSL_FIPS */
|
||||
@@ -0,0 +1,180 @@
|
||||
/* crypto/dsa/dsatest.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/fips.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
/* seed, out_p, out_q, out_g are taken the NIST test vectors */
|
||||
|
||||
static unsigned char seed[20] = {
|
||||
0x77, 0x8f, 0x40, 0x74, 0x6f, 0x66, 0xbe, 0x33, 0xce, 0xbe, 0x99, 0x34,
|
||||
0x4c, 0xfc, 0xf3, 0x28, 0xaa, 0x70, 0x2d, 0x3a
|
||||
};
|
||||
|
||||
static unsigned char out_p[] = {
|
||||
0xf7, 0x7c, 0x1b, 0x83, 0xd8, 0xe8, 0x5c, 0x7f, 0x85, 0x30, 0x17, 0x57,
|
||||
0x21, 0x95, 0xfe, 0x26, 0x04, 0xeb, 0x47, 0x4c, 0x3a, 0x4a, 0x81, 0x4b,
|
||||
0x71, 0x2e, 0xed, 0x6e, 0x4f, 0x3d, 0x11, 0x0f, 0x7c, 0xfe, 0x36, 0x43,
|
||||
0x51, 0xd9, 0x81, 0x39, 0x17, 0xdf, 0x62, 0xf6, 0x9c, 0x01, 0xa8, 0x69,
|
||||
0x71, 0xdd, 0x29, 0x7f, 0x47, 0xe6, 0x65, 0xa6, 0x22, 0xe8, 0x6a, 0x12,
|
||||
0x2b, 0xc2, 0x81, 0xff, 0x32, 0x70, 0x2f, 0x9e, 0xca, 0x53, 0x26, 0x47,
|
||||
0x0f, 0x59, 0xd7, 0x9e, 0x2c, 0xa5, 0x07, 0xc4, 0x49, 0x52, 0xa3, 0xe4,
|
||||
0x6b, 0x04, 0x00, 0x25, 0x49, 0xe2, 0xe6, 0x7f, 0x28, 0x78, 0x97, 0xb8,
|
||||
0x3a, 0x32, 0x14, 0x38, 0xa2, 0x51, 0x33, 0x22, 0x44, 0x7e, 0xd7, 0xef,
|
||||
0x45, 0xdb, 0x06, 0x4a, 0xd2, 0x82, 0x4a, 0x82, 0x2c, 0xb1, 0xd7, 0xd8,
|
||||
0xb6, 0x73, 0x00, 0x4d, 0x94, 0x77, 0x94, 0xef
|
||||
};
|
||||
|
||||
static unsigned char out_q[] = {
|
||||
0xd4, 0x0a, 0xac, 0x9f, 0xbd, 0x8c, 0x80, 0xc2, 0x38, 0x7e, 0x2e, 0x0c,
|
||||
0x52, 0x5c, 0xea, 0x34, 0xa1, 0x83, 0x32, 0xf3
|
||||
};
|
||||
|
||||
static unsigned char out_g[] = {
|
||||
0x34, 0x73, 0x8b, 0x57, 0x84, 0x8e, 0x55, 0xbf, 0x57, 0xcc, 0x41, 0xbb,
|
||||
0x5e, 0x2b, 0xd5, 0x42, 0xdd, 0x24, 0x22, 0x2a, 0x09, 0xea, 0x26, 0x1e,
|
||||
0x17, 0x65, 0xcb, 0x1a, 0xb3, 0x12, 0x44, 0xa3, 0x9e, 0x99, 0xe9, 0x63,
|
||||
0xeb, 0x30, 0xb1, 0x78, 0x7b, 0x09, 0x40, 0x30, 0xfa, 0x83, 0xc2, 0x35,
|
||||
0xe1, 0xc4, 0x2d, 0x74, 0x1a, 0xb1, 0x83, 0x54, 0xd8, 0x29, 0xf4, 0xcf,
|
||||
0x7f, 0x6f, 0x67, 0x1c, 0x36, 0x49, 0xee, 0x6c, 0xa2, 0x3c, 0x2d, 0x6a,
|
||||
0xe9, 0xd3, 0x9a, 0xf6, 0x57, 0x78, 0x6f, 0xfd, 0x33, 0xcd, 0x3c, 0xed,
|
||||
0xfd, 0xd4, 0x41, 0xe6, 0x5c, 0x8b, 0xe0, 0x68, 0x31, 0x47, 0x47, 0xaf,
|
||||
0x12, 0xa7, 0xf9, 0x32, 0x0d, 0x94, 0x15, 0x48, 0xd0, 0x54, 0x85, 0xb2,
|
||||
0x04, 0xb5, 0x4d, 0xd4, 0x9d, 0x05, 0x22, 0x25, 0xd9, 0xfd, 0x6c, 0x36,
|
||||
0xef, 0xbe, 0x69, 0x6c, 0x55, 0xf4, 0xee, 0xec
|
||||
};
|
||||
|
||||
static const unsigned char str1[] = "12345678901234567890";
|
||||
|
||||
void FIPS_corrupt_dsa()
|
||||
{
|
||||
++seed[0];
|
||||
}
|
||||
|
||||
int FIPS_selftest_dsa()
|
||||
{
|
||||
DSA *dsa = NULL;
|
||||
int counter, i, j, ret = 0;
|
||||
unsigned int slen;
|
||||
unsigned char buf[256];
|
||||
unsigned long h;
|
||||
EVP_MD_CTX mctx;
|
||||
EVP_PKEY pk;
|
||||
|
||||
EVP_MD_CTX_init(&mctx);
|
||||
|
||||
dsa = FIPS_dsa_new();
|
||||
|
||||
if (dsa == NULL)
|
||||
goto err;
|
||||
if (!DSA_generate_parameters_ex(dsa, 1024, seed, 20, &counter, &h, NULL))
|
||||
goto err;
|
||||
if (counter != 378)
|
||||
goto err;
|
||||
if (h != 2)
|
||||
goto err;
|
||||
i = BN_bn2bin(dsa->q, buf);
|
||||
j = sizeof(out_q);
|
||||
if (i != j || memcmp(buf, out_q, i) != 0)
|
||||
goto err;
|
||||
|
||||
i = BN_bn2bin(dsa->p, buf);
|
||||
j = sizeof(out_p);
|
||||
if (i != j || memcmp(buf, out_p, i) != 0)
|
||||
goto err;
|
||||
|
||||
i = BN_bn2bin(dsa->g, buf);
|
||||
j = sizeof(out_g);
|
||||
if (i != j || memcmp(buf, out_g, i) != 0)
|
||||
goto err;
|
||||
DSA_generate_key(dsa);
|
||||
pk.type = EVP_PKEY_DSA;
|
||||
pk.pkey.dsa = dsa;
|
||||
|
||||
if (!EVP_SignInit_ex(&mctx, EVP_dss1(), NULL))
|
||||
goto err;
|
||||
if (!EVP_SignUpdate(&mctx, str1, 20))
|
||||
goto err;
|
||||
if (!EVP_SignFinal(&mctx, buf, &slen, &pk))
|
||||
goto err;
|
||||
|
||||
if (!EVP_VerifyInit_ex(&mctx, EVP_dss1(), NULL))
|
||||
goto err;
|
||||
if (!EVP_VerifyUpdate(&mctx, str1, 20))
|
||||
goto err;
|
||||
if (EVP_VerifyFinal(&mctx, buf, slen, &pk) != 1)
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_cleanup(&mctx);
|
||||
if (dsa)
|
||||
FIPS_dsa_free(dsa);
|
||||
if (ret == 0)
|
||||
FIPSerr(FIPS_F_FIPS_SELFTEST_DSA, FIPS_R_SELFTEST_FAILED);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,267 @@
|
||||
/* fips_dsa_sign.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2007.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
/*
|
||||
* FIPS versions of DSA_sign() and DSA_verify(). These include a tiny ASN1
|
||||
* encoder/decoder to handle the specific case of a DSA signature.
|
||||
*/
|
||||
|
||||
# if 0
|
||||
int FIPS_dsa_size(DSA *r)
|
||||
{
|
||||
int ilen;
|
||||
ilen = BN_num_bytes(r->q);
|
||||
if (ilen > 20)
|
||||
return -1;
|
||||
/* If MSB set need padding byte */
|
||||
ilen++;
|
||||
/*
|
||||
* Also need 2 bytes INTEGER header for r and s plus 2 bytes SEQUENCE
|
||||
* header making 6 in total.
|
||||
*/
|
||||
return ilen * 2 + 6;
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Tiny ASN1 encoder for DSA_SIG structure. We can assume r, s smaller than
|
||||
* 0x80 octets as by the DSA standards they will be less than 2^160
|
||||
*/
|
||||
|
||||
int FIPS_dsa_sig_encode(unsigned char *out, DSA_SIG *sig)
|
||||
{
|
||||
int rlen, slen, rpad, spad, seqlen;
|
||||
rlen = BN_num_bytes(sig->r);
|
||||
if (rlen > 20)
|
||||
return -1;
|
||||
if (BN_num_bits(sig->r) & 0x7)
|
||||
rpad = 0;
|
||||
else
|
||||
rpad = 1;
|
||||
slen = BN_num_bytes(sig->s);
|
||||
if (slen > 20)
|
||||
return -1;
|
||||
if (BN_num_bits(sig->s) & 0x7)
|
||||
spad = 0;
|
||||
else
|
||||
spad = 1;
|
||||
/* Length of SEQUENCE, (1 tag + 1 len octet) * 2 + content octets */
|
||||
seqlen = rlen + rpad + slen + spad + 4;
|
||||
/* Actual encoded length: include SEQUENCE header */
|
||||
if (!out)
|
||||
return seqlen + 2;
|
||||
|
||||
/* Output SEQUENCE header */
|
||||
*out++ = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
|
||||
*out++ = (unsigned char)seqlen;
|
||||
|
||||
/* Output r */
|
||||
*out++ = V_ASN1_INTEGER;
|
||||
*out++ = (unsigned char)(rlen + rpad);
|
||||
if (rpad)
|
||||
*out++ = 0;
|
||||
BN_bn2bin(sig->r, out);
|
||||
out += rlen;
|
||||
|
||||
/* Output s */
|
||||
*out++ = V_ASN1_INTEGER;
|
||||
*out++ = (unsigned char)(slen + spad);
|
||||
if (spad)
|
||||
*out++ = 0;
|
||||
BN_bn2bin(sig->s, out);
|
||||
return seqlen + 2;
|
||||
}
|
||||
|
||||
/* Companion DSA_SIG decoder */
|
||||
|
||||
int FIPS_dsa_sig_decode(DSA_SIG *sig, const unsigned char *in, int inlen)
|
||||
{
|
||||
int seqlen, rlen, slen;
|
||||
const unsigned char *rbin;
|
||||
/* Sanity check */
|
||||
|
||||
/* Need SEQUENCE tag */
|
||||
if (*in++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED))
|
||||
return 0;
|
||||
/* Get length octet */
|
||||
seqlen = *in++;
|
||||
/* Check sensible length value */
|
||||
if (seqlen < 4 || seqlen > 0x7F)
|
||||
return 0;
|
||||
/* Check INTEGER tag */
|
||||
if (*in++ != V_ASN1_INTEGER)
|
||||
return 0;
|
||||
rlen = *in++;
|
||||
seqlen -= 2 + rlen;
|
||||
/* Check sensible seqlen value */
|
||||
if (seqlen < 2)
|
||||
return 0;
|
||||
rbin = in;
|
||||
in += rlen;
|
||||
/* Check INTEGER tag */
|
||||
if (*in++ != V_ASN1_INTEGER)
|
||||
return 0;
|
||||
slen = *in++;
|
||||
/*
|
||||
* Remaining bytes of SEQUENCE should exactly match encoding of s
|
||||
*/
|
||||
if (seqlen != (slen + 2))
|
||||
return 0;
|
||||
if (!sig->r && !(sig->r = BN_new()))
|
||||
return 0;
|
||||
if (!sig->s && !(sig->s = BN_new()))
|
||||
return 0;
|
||||
if (!BN_bin2bn(rbin, rlen, sig->r))
|
||||
return 0;
|
||||
if (!BN_bin2bn(in, slen, sig->s))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fips_dsa_sign(int type, const unsigned char *x, int y,
|
||||
unsigned char *sig, unsigned int *siglen,
|
||||
EVP_MD_SVCTX * sv)
|
||||
{
|
||||
DSA *dsa = sv->key;
|
||||
unsigned char dig[EVP_MAX_MD_SIZE];
|
||||
unsigned int dlen;
|
||||
DSA_SIG *s;
|
||||
EVP_DigestFinal_ex(sv->mctx, dig, &dlen);
|
||||
s = dsa->meth->dsa_do_sign(dig, dlen, dsa);
|
||||
OPENSSL_cleanse(dig, dlen);
|
||||
if (s == NULL) {
|
||||
*siglen = 0;
|
||||
return 0;
|
||||
}
|
||||
*siglen = FIPS_dsa_sig_encode(sig, s);
|
||||
DSA_SIG_free(s);
|
||||
if (*siglen < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fips_dsa_verify(int type, const unsigned char *x, int y,
|
||||
const unsigned char *sigbuf, unsigned int siglen,
|
||||
EVP_MD_SVCTX * sv)
|
||||
{
|
||||
DSA *dsa = sv->key;
|
||||
DSA_SIG *s;
|
||||
int ret = -1;
|
||||
unsigned char dig[EVP_MAX_MD_SIZE];
|
||||
unsigned int dlen;
|
||||
|
||||
s = DSA_SIG_new();
|
||||
if (s == NULL)
|
||||
return ret;
|
||||
if (!FIPS_dsa_sig_decode(s, sigbuf, siglen))
|
||||
goto err;
|
||||
EVP_DigestFinal_ex(sv->mctx, dig, &dlen);
|
||||
ret = dsa->meth->dsa_do_verify(dig, dlen, s, dsa);
|
||||
OPENSSL_cleanse(dig, dlen);
|
||||
err:
|
||||
DSA_SIG_free(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return SHA1_Init(ctx->md_data);
|
||||
}
|
||||
|
||||
static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
return SHA1_Update(ctx->md_data, data, count);
|
||||
}
|
||||
|
||||
static int final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
return SHA1_Final(md, ctx->md_data);
|
||||
}
|
||||
|
||||
static const EVP_MD dss1_md = {
|
||||
NID_dsa,
|
||||
NID_dsaWithSHA1,
|
||||
SHA_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX,
|
||||
init,
|
||||
update,
|
||||
final,
|
||||
NULL,
|
||||
NULL,
|
||||
(evp_sign_method *) fips_dsa_sign,
|
||||
(evp_verify_method *) fips_dsa_verify,
|
||||
{EVP_PKEY_DSA, EVP_PKEY_DSA2, EVP_PKEY_DSA3, EVP_PKEY_DSA4, 0},
|
||||
SHA_CBLOCK,
|
||||
sizeof(EVP_MD *) + sizeof(SHA_CTX),
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_dss1(void)
|
||||
{
|
||||
return (&dss1_md);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,528 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/fips_rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "fips_locl.h"
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
# include <openssl/fips.h>
|
||||
|
||||
# ifndef PATH_MAX
|
||||
# define PATH_MAX 1024
|
||||
# endif
|
||||
|
||||
static int fips_selftest_fail;
|
||||
static int fips_mode;
|
||||
static const void *fips_rand_check;
|
||||
|
||||
static void fips_set_mode(int onoff)
|
||||
{
|
||||
int owning_thread = fips_is_owning_thread();
|
||||
|
||||
if (fips_is_started()) {
|
||||
if (!owning_thread)
|
||||
fips_w_lock();
|
||||
fips_mode = onoff;
|
||||
if (!owning_thread)
|
||||
fips_w_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
static void fips_set_rand_check(const void *rand_check)
|
||||
{
|
||||
int owning_thread = fips_is_owning_thread();
|
||||
|
||||
if (fips_is_started()) {
|
||||
if (!owning_thread)
|
||||
fips_w_lock();
|
||||
fips_rand_check = rand_check;
|
||||
if (!owning_thread)
|
||||
fips_w_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
int FIPS_mode(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int owning_thread = fips_is_owning_thread();
|
||||
|
||||
if (fips_is_started()) {
|
||||
if (!owning_thread)
|
||||
fips_r_lock();
|
||||
ret = fips_mode;
|
||||
if (!owning_thread)
|
||||
fips_r_unlock();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const void *FIPS_rand_check(void)
|
||||
{
|
||||
const void *ret = 0;
|
||||
int owning_thread = fips_is_owning_thread();
|
||||
|
||||
if (fips_is_started()) {
|
||||
if (!owning_thread)
|
||||
fips_r_lock();
|
||||
ret = fips_rand_check;
|
||||
if (!owning_thread)
|
||||
fips_r_unlock();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FIPS_selftest_failed(void)
|
||||
{
|
||||
int ret = 0;
|
||||
if (fips_is_started()) {
|
||||
int owning_thread = fips_is_owning_thread();
|
||||
|
||||
if (!owning_thread)
|
||||
fips_r_lock();
|
||||
ret = fips_selftest_fail;
|
||||
if (!owning_thread)
|
||||
fips_r_unlock();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Selftest failure fatal exit routine. This will be called during *any*
|
||||
* cryptographic operation. It has the minimum overhead possible to avoid too
|
||||
* big a performance hit.
|
||||
*/
|
||||
|
||||
void FIPS_selftest_check(void)
|
||||
{
|
||||
if (fips_selftest_fail) {
|
||||
OpenSSLDie(__FILE__, __LINE__, "FATAL FIPS SELFTEST FAILURE");
|
||||
}
|
||||
}
|
||||
|
||||
void fips_set_selftest_fail(void)
|
||||
{
|
||||
fips_selftest_fail = 1;
|
||||
}
|
||||
|
||||
int FIPS_selftest()
|
||||
{
|
||||
|
||||
return FIPS_selftest_sha1()
|
||||
&& FIPS_selftest_hmac()
|
||||
&& FIPS_selftest_aes()
|
||||
&& FIPS_selftest_des()
|
||||
&& FIPS_selftest_rsa()
|
||||
&& FIPS_selftest_dsa();
|
||||
}
|
||||
|
||||
extern const void *FIPS_text_start(), *FIPS_text_end();
|
||||
extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
|
||||
unsigned char FIPS_signature[20] = { 0 };
|
||||
|
||||
static const char FIPS_hmac_key[] = "etaonrishdlcupfm";
|
||||
|
||||
unsigned int FIPS_incore_fingerprint(unsigned char *sig, unsigned int len)
|
||||
{
|
||||
const unsigned char *p1 = FIPS_text_start();
|
||||
const unsigned char *p2 = FIPS_text_end();
|
||||
const unsigned char *p3 = FIPS_rodata_start;
|
||||
const unsigned char *p4 = FIPS_rodata_end;
|
||||
HMAC_CTX c;
|
||||
|
||||
HMAC_CTX_init(&c);
|
||||
HMAC_Init(&c, FIPS_hmac_key, strlen(FIPS_hmac_key), EVP_sha1());
|
||||
|
||||
/* detect overlapping regions */
|
||||
if (p1 <= p3 && p2 >= p3)
|
||||
p3 = p1, p4 = p2 > p4 ? p2 : p4, p1 = NULL, p2 = NULL;
|
||||
else if (p3 <= p1 && p4 >= p1)
|
||||
p3 = p3, p4 = p2 > p4 ? p2 : p4, p1 = NULL, p2 = NULL;
|
||||
|
||||
if (p1)
|
||||
HMAC_Update(&c, p1, (size_t)p2 - (size_t)p1);
|
||||
|
||||
if (FIPS_signature >= p3 && FIPS_signature < p4) {
|
||||
/* "punch" hole */
|
||||
HMAC_Update(&c, p3, (size_t)FIPS_signature - (size_t)p3);
|
||||
p3 = FIPS_signature + sizeof(FIPS_signature);
|
||||
if (p3 < p4)
|
||||
HMAC_Update(&c, p3, (size_t)p4 - (size_t)p3);
|
||||
} else
|
||||
HMAC_Update(&c, p3, (size_t)p4 - (size_t)p3);
|
||||
|
||||
HMAC_Final(&c, sig, &len);
|
||||
HMAC_CTX_cleanup(&c);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int FIPS_check_incore_fingerprint(void)
|
||||
{
|
||||
unsigned char sig[EVP_MAX_MD_SIZE];
|
||||
unsigned int len;
|
||||
# if defined(__sgi) && (defined(__mips) || defined(mips))
|
||||
extern int __dso_displacement[];
|
||||
# else
|
||||
extern int OPENSSL_NONPIC_relocated;
|
||||
# endif
|
||||
|
||||
if (FIPS_text_start() == NULL) {
|
||||
FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,
|
||||
FIPS_R_UNSUPPORTED_PLATFORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = FIPS_incore_fingerprint(sig, sizeof(sig));
|
||||
|
||||
if (len != sizeof(FIPS_signature) ||
|
||||
memcmp(FIPS_signature, sig, sizeof(FIPS_signature))) {
|
||||
if (FIPS_signature >= FIPS_rodata_start
|
||||
&& FIPS_signature < FIPS_rodata_end)
|
||||
FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,
|
||||
FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING);
|
||||
# if defined(__sgi) && (defined(__mips) || defined(mips))
|
||||
else if (__dso_displacement != NULL)
|
||||
# else
|
||||
else if (OPENSSL_NONPIC_relocated)
|
||||
# endif
|
||||
FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,
|
||||
FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED);
|
||||
else
|
||||
FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,
|
||||
FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FIPS_mode_set(int onoff)
|
||||
{
|
||||
int fips_set_owning_thread();
|
||||
int fips_clear_owning_thread();
|
||||
int ret = 0;
|
||||
|
||||
fips_w_lock();
|
||||
fips_set_started();
|
||||
fips_set_owning_thread();
|
||||
|
||||
if (onoff) {
|
||||
unsigned char buf[48];
|
||||
|
||||
fips_selftest_fail = 0;
|
||||
|
||||
/*
|
||||
* Don't go into FIPS mode twice, just so we can do automagic seeding
|
||||
*/
|
||||
if (FIPS_mode()) {
|
||||
FIPSerr(FIPS_F_FIPS_MODE_SET, FIPS_R_FIPS_MODE_ALREADY_SET);
|
||||
fips_selftest_fail = 1;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
# ifdef OPENSSL_IA32_SSE2
|
||||
if ((OPENSSL_ia32cap & (1 << 25 | 1 << 26)) != (1 << 25 | 1 << 26)) {
|
||||
FIPSerr(FIPS_F_FIPS_MODE_SET, FIPS_R_UNSUPPORTED_PLATFORM);
|
||||
fips_selftest_fail = 1;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (fips_signature_witness() != FIPS_signature) {
|
||||
FIPSerr(FIPS_F_FIPS_MODE_SET, FIPS_R_CONTRADICTING_EVIDENCE);
|
||||
fips_selftest_fail = 1;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!FIPS_check_incore_fingerprint()) {
|
||||
fips_selftest_fail = 1;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Perform RNG KAT before seeding */
|
||||
if (!FIPS_selftest_rng()) {
|
||||
fips_selftest_fail = 1;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* automagically seed PRNG if not already seeded */
|
||||
if (!FIPS_rand_status()) {
|
||||
if (RAND_bytes(buf, sizeof buf) <= 0) {
|
||||
fips_selftest_fail = 1;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
FIPS_rand_set_key(buf, 32);
|
||||
FIPS_rand_seed(buf + 32, 16);
|
||||
}
|
||||
|
||||
/* now switch into FIPS mode */
|
||||
fips_set_rand_check(FIPS_rand_method());
|
||||
RAND_set_rand_method(FIPS_rand_method());
|
||||
if (FIPS_selftest())
|
||||
fips_set_mode(1);
|
||||
else {
|
||||
fips_selftest_fail = 1;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
fips_set_mode(0);
|
||||
fips_selftest_fail = 0;
|
||||
ret = 1;
|
||||
end:
|
||||
fips_clear_owning_thread();
|
||||
fips_w_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fips_w_lock(void)
|
||||
{
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_FIPS);
|
||||
}
|
||||
|
||||
void fips_w_unlock(void)
|
||||
{
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_FIPS);
|
||||
}
|
||||
|
||||
void fips_r_lock(void)
|
||||
{
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_FIPS);
|
||||
}
|
||||
|
||||
void fips_r_unlock(void)
|
||||
{
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_FIPS);
|
||||
}
|
||||
|
||||
static int fips_started = 0;
|
||||
static unsigned long fips_thread = 0;
|
||||
|
||||
void fips_set_started(void)
|
||||
{
|
||||
fips_started = 1;
|
||||
}
|
||||
|
||||
int fips_is_started(void)
|
||||
{
|
||||
return fips_started;
|
||||
}
|
||||
|
||||
int fips_is_owning_thread(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fips_is_started()) {
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
|
||||
if (fips_thread != 0 && fips_thread == CRYPTO_thread_id())
|
||||
ret = 1;
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fips_set_owning_thread(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fips_is_started()) {
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
|
||||
if (fips_thread == 0) {
|
||||
fips_thread = CRYPTO_thread_id();
|
||||
ret = 1;
|
||||
}
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fips_clear_owning_thread(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fips_is_started()) {
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
|
||||
if (fips_thread == CRYPTO_thread_id()) {
|
||||
fips_thread = 0;
|
||||
ret = 1;
|
||||
}
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char *fips_signature_witness(void)
|
||||
{
|
||||
extern unsigned char FIPS_signature[];
|
||||
return FIPS_signature;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generalized public key test routine. Signs and verifies the data supplied
|
||||
* in tbs using mesage digest md and setting option digest flags md_flags. If
|
||||
* the 'kat' parameter is not NULL it will additionally check the signature
|
||||
* matches it: a known answer test The string "fail_str" is used for
|
||||
* identification purposes in case of failure.
|
||||
*/
|
||||
|
||||
int fips_pkey_signature_test(EVP_PKEY *pkey,
|
||||
const unsigned char *tbs, int tbslen,
|
||||
const unsigned char *kat, unsigned int katlen,
|
||||
const EVP_MD *digest, unsigned int md_flags,
|
||||
const char *fail_str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char sigtmp[256], *sig = sigtmp;
|
||||
unsigned int siglen;
|
||||
EVP_MD_CTX mctx;
|
||||
EVP_MD_CTX_init(&mctx);
|
||||
|
||||
if ((pkey->type == EVP_PKEY_RSA)
|
||||
&& (RSA_size(pkey->pkey.rsa) > sizeof(sigtmp)))
|
||||
{
|
||||
sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa));
|
||||
if (!sig)
|
||||
{
|
||||
FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (tbslen == -1)
|
||||
tbslen = strlen((char *)tbs);
|
||||
|
||||
if (md_flags)
|
||||
M_EVP_MD_CTX_set_flags(&mctx, md_flags);
|
||||
|
||||
if (!EVP_SignInit_ex(&mctx, digest, NULL))
|
||||
goto error;
|
||||
if (!EVP_SignUpdate(&mctx, tbs, tbslen))
|
||||
goto error;
|
||||
if (!EVP_SignFinal(&mctx, sig, &siglen, pkey))
|
||||
goto error;
|
||||
|
||||
if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen)))
|
||||
goto error;
|
||||
|
||||
if (!EVP_VerifyInit_ex(&mctx, digest, NULL))
|
||||
goto error;
|
||||
if (!EVP_VerifyUpdate(&mctx, tbs, tbslen))
|
||||
goto error;
|
||||
ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey);
|
||||
|
||||
error:
|
||||
if (sig != sigtmp)
|
||||
OPENSSL_free(sig);
|
||||
EVP_MD_CTX_cleanup(&mctx);
|
||||
if (ret != 1)
|
||||
{
|
||||
FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE);
|
||||
if (fail_str)
|
||||
ERR_add_error_data(2, "Type=", fail_str);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generalized symmetric cipher test routine. Encrypt data, verify result
|
||||
* against known answer, decrypt and compare with original plaintext.
|
||||
*/
|
||||
|
||||
int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
const unsigned char *plaintext,
|
||||
const unsigned char *ciphertext, int len)
|
||||
{
|
||||
unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE];
|
||||
unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE];
|
||||
OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE);
|
||||
if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1) <= 0)
|
||||
return 0;
|
||||
EVP_Cipher(ctx, citmp, plaintext, len);
|
||||
if (memcmp(citmp, ciphertext, len))
|
||||
return 0;
|
||||
if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0) <= 0)
|
||||
return 0;
|
||||
EVP_Cipher(ctx, pltmp, citmp, len);
|
||||
if (memcmp(pltmp, plaintext, len))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# if 0
|
||||
/*
|
||||
* The purpose of this is to ensure the error code exists and the function
|
||||
* name is to keep the error checking script quiet
|
||||
*/
|
||||
void hash_final(void)
|
||||
{
|
||||
FIPSerr(FIPS_F_HASH_FINAL, FIPS_R_NON_FIPS_METHOD);
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,199 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
|
||||
* and usage in source and binary forms are granted according to the
|
||||
* OpenSSL license.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if defined(__DECC)
|
||||
# include <c_asm.h>
|
||||
# pragma __nostandard
|
||||
#endif
|
||||
|
||||
#include "e_os.h"
|
||||
|
||||
#if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
|
||||
# if (defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \
|
||||
(defined(__sgi) && (defined(__mips) || defined(mips))) || \
|
||||
(defined(__osf__) && defined(__alpha)) || \
|
||||
(defined(__linux) && (defined(__arm) || defined(__arm__))) || \
|
||||
(defined(__i386) || defined(__i386__)) || \
|
||||
(defined(__x86_64) || defined(__x86_64__)) || \
|
||||
defined(__ANDROID__) || \
|
||||
(defined(vax) || defined(__vax__))
|
||||
# define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__xlC__) && __xlC__>=0x600 && (defined(_POWER) || defined(_ARCH_PPC))
|
||||
static void *instruction_pointer_xlc(void);
|
||||
# pragma mc_func instruction_pointer_xlc {\
|
||||
"7c0802a6" /* mflr r0 */ \
|
||||
"48000005" /* bl $+4 */ \
|
||||
"7c6802a6" /* mflr r3 */ \
|
||||
"7c0803a6" /* mtlr r0 */ }
|
||||
# pragma reg_killed_by instruction_pointer_xlc gr0 gr3
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED(ret) (ret=instruction_pointer_xlc());
|
||||
#endif
|
||||
|
||||
#ifdef FIPS_START
|
||||
# define FIPS_ref_point FIPS_text_start
|
||||
/*
|
||||
* Some compilers put string literals into a separate segment. As we are
|
||||
* mostly interested to hash AES tables in .rodata, we declare reference
|
||||
* points accordingly. In case you wonder, the values are big-endian encoded
|
||||
* variable names, just to prevent these arrays from being merged by linker.
|
||||
*/
|
||||
const unsigned int FIPS_rodata_start[] =
|
||||
{ 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 };
|
||||
#else
|
||||
# define FIPS_ref_point FIPS_text_end
|
||||
const unsigned int FIPS_rodata_end[] =
|
||||
{ 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b };
|
||||
#endif
|
||||
|
||||
/*
|
||||
* I declare reference function as static in order to avoid certain
|
||||
* pitfalls in -dynamic linker behaviour...
|
||||
*/
|
||||
static void *instruction_pointer(void)
|
||||
{
|
||||
void *ret = NULL;
|
||||
/*
|
||||
* These are ABI-neutral CPU-specific snippets. ABI-neutrality means that
|
||||
* they are designed to work under any OS running on particular CPU,
|
||||
* which is why you don't find any #ifdef THIS_OR_THAT_OS in this
|
||||
* function.
|
||||
*/
|
||||
#if defined(INSTRUCTION_POINTER_IMPLEMENTED)
|
||||
INSTRUCTION_POINTER_IMPLEMENTED(ret);
|
||||
#elif defined(__GNUC__) && __GNUC__>=2
|
||||
# if defined(__alpha) || defined(__alpha__)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
__asm __volatile("br %0,1f\n1:":"=r"(ret));
|
||||
# elif defined(__i386) || defined(__i386__)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
__asm __volatile("call 1f\n1: popl %0":"=r"(ret));
|
||||
ret = (void *)((size_t)ret & ~3UL); /* align for better performance */
|
||||
# elif defined(__ia64) || defined(__ia64__)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
__asm __volatile("mov %0=ip":"=r"(ret));
|
||||
# elif defined(__hppa) || defined(__hppa__) || defined(__pa_risc)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
__asm __volatile("blr %%r0,%0\n\tnop":"=r"(ret));
|
||||
ret = (void *)((size_t)ret & ~3UL); /* mask privilege level */
|
||||
# elif defined(__mips) || defined(__mips__)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
void *scratch;
|
||||
__asm __volatile("move %1,$31\n\t" /* save ra */
|
||||
"bal .+8; nop\n\t" "move %0,$31\n\t"
|
||||
/* restore ra */
|
||||
"move $31,%1":"=r"(ret), "=r"(scratch));
|
||||
# elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \
|
||||
defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \
|
||||
defined(__PPC64__) || defined(__powerpc64__)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
void *scratch;
|
||||
__asm __volatile("mfspr %1,8\n\t" /* save lr */
|
||||
"bl $+4\n\t" "mfspr %0,8\n\t" /* mflr ret */
|
||||
"mtspr 8,%1" /* restore lr */
|
||||
:"=r"(ret), "=r"(scratch));
|
||||
# elif defined(__s390__) || defined(__s390x__)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
__asm __volatile("bras %0,1f\n1:":"=r"(ret));
|
||||
ret = (void *)((size_t)ret & ~3UL);
|
||||
# elif defined(__sparc) || defined(__sparc__) || defined(__sparcv9)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
void *scratch;
|
||||
__asm __volatile("mov %%o7,%1\n\t"
|
||||
"call .+8; nop\n\t"
|
||||
"mov %%o7,%0\n\t"
|
||||
"mov %1,%%o7":"=r"(ret), "=r"(scratch));
|
||||
# elif defined(__x86_64) || defined(__x86_64__)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
__asm __volatile("leaq 0(%%rip),%0":"=r"(ret));
|
||||
ret = (void *)((size_t)ret & ~3UL); /* align for better performance */
|
||||
# endif
|
||||
#elif defined(__DECC) && defined(__alpha)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
ret = (void *)(size_t)asm("br %v0,1f\n1:");
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
# define INSTRUCTION_POINTER_IMPLEMENTED
|
||||
void *scratch;
|
||||
_asm {
|
||||
call self
|
||||
self:pop eax
|
||||
mov scratch, eax} ret = (void *)((size_t)scratch & ~3UL);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns pointer to an instruction in the vicinity of
|
||||
* its entry point, but not outside this object module. This guarantees
|
||||
* that sequestered code is covered...
|
||||
*/
|
||||
void *FIPS_ref_point()
|
||||
{
|
||||
#if defined(INSTRUCTION_POINTER_IMPLEMENTED)
|
||||
return instruction_pointer();
|
||||
/*
|
||||
* Below we essentially cover vendor compilers which do not support
|
||||
* inline assembler...
|
||||
*/
|
||||
#elif defined(_AIX)
|
||||
struct {
|
||||
void *ip, *gp, *env;
|
||||
} *p = (void *)instruction_pointer;
|
||||
return p->ip;
|
||||
#elif defined(_HPUX_SOURCE)
|
||||
# if defined(__hppa) || defined(__hppa__)
|
||||
struct {
|
||||
void *i[4];
|
||||
} *p = (void *)FIPS_ref_point;
|
||||
|
||||
if (sizeof(p) == 8) /* 64-bit */
|
||||
return p->i[2];
|
||||
else if ((size_t)p & 2) {
|
||||
p = (void *)((size_t)p & ~3UL);
|
||||
return p->i[0];
|
||||
} else
|
||||
return (void *)p;
|
||||
# elif defined(__ia64) || defined(__ia64__)
|
||||
struct {
|
||||
unsigned long long ip, gp;
|
||||
} *p = (void *)instruction_pointer;
|
||||
return (void *)(size_t)p->ip;
|
||||
# endif
|
||||
#elif (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__))
|
||||
/* applies to both alpha and ia64 */
|
||||
struct {
|
||||
unsigned __int64 opaque, ip;
|
||||
} *p = (void *)instruction_pointer;
|
||||
return (void *)(size_t)p->ip;
|
||||
#elif defined(__VOS__)
|
||||
/* applies to both pa-risc and ia32 */
|
||||
struct {
|
||||
void *dp, *ip, *gp;
|
||||
} *p = (void *)instruction_pointer;
|
||||
return p->ip;
|
||||
#elif defined(_WIN32)
|
||||
# if defined(_WIN64) && defined(_M_IA64)
|
||||
struct {
|
||||
void *ip, *gp;
|
||||
} *p = (void *)FIPS_ref_point;
|
||||
return p->ip;
|
||||
# else
|
||||
return (void *)FIPS_ref_point;
|
||||
# endif
|
||||
/*
|
||||
* In case you wonder why there is no #ifdef __linux. All Linux targets
|
||||
* are GCC-based and therefore are covered by instruction_pointer above
|
||||
* [well, some are covered by by the one below]...
|
||||
*/
|
||||
#elif defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
|
||||
return (void *)instruction_pointer;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void fips_w_lock(void);
|
||||
void fips_w_unlock(void);
|
||||
void fips_r_lock(void);
|
||||
void fips_r_unlock(void);
|
||||
int fips_is_started(void);
|
||||
void fips_set_started(void);
|
||||
int fips_is_owning_thread(void);
|
||||
int fips_set_owning_thread(void);
|
||||
void fips_set_selftest_fail(void);
|
||||
int fips_clear_owning_thread(void);
|
||||
unsigned char *fips_signature_witness(void);
|
||||
int fips_check_rsa(RSA *rsa);
|
||||
|
||||
# define FIPS_MAX_CIPHER_TEST_SIZE 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,182 @@
|
||||
/* crypto/hmac/hmac.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/fips.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
void HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
|
||||
const EVP_MD *md, ENGINE *impl)
|
||||
{
|
||||
int i, j, reset = 0;
|
||||
unsigned char pad[HMAC_MAX_MD_CBLOCK];
|
||||
|
||||
if (md != NULL) {
|
||||
reset = 1;
|
||||
ctx->md = md;
|
||||
} else
|
||||
md = ctx->md;
|
||||
|
||||
if (key != NULL) {
|
||||
if (FIPS_mode() && !(md->flags & EVP_MD_FLAG_FIPS)
|
||||
&& (!(ctx->md_ctx.flags & EVP_MD_CTX_FLAG_NON_FIPS_ALLOW)
|
||||
|| !(ctx->i_ctx.flags & EVP_MD_CTX_FLAG_NON_FIPS_ALLOW)
|
||||
|| !(ctx->o_ctx.flags & EVP_MD_CTX_FLAG_NON_FIPS_ALLOW)))
|
||||
OpenSSLDie(__FILE__, __LINE__,
|
||||
"HMAC: digest not allowed in FIPS mode");
|
||||
|
||||
reset = 1;
|
||||
j = M_EVP_MD_block_size(md);
|
||||
OPENSSL_assert(j <= (int)sizeof ctx->key);
|
||||
if (j < len) {
|
||||
EVP_DigestInit_ex(&ctx->md_ctx, md, impl);
|
||||
EVP_DigestUpdate(&ctx->md_ctx, key, len);
|
||||
EVP_DigestFinal_ex(&(ctx->md_ctx), ctx->key, &ctx->key_length);
|
||||
} else {
|
||||
OPENSSL_assert(len <= (int)sizeof ctx->key);
|
||||
memcpy(ctx->key, key, len);
|
||||
ctx->key_length = len;
|
||||
}
|
||||
if (ctx->key_length != HMAC_MAX_MD_CBLOCK)
|
||||
memset(&ctx->key[ctx->key_length], 0,
|
||||
HMAC_MAX_MD_CBLOCK - ctx->key_length);
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++)
|
||||
pad[i] = 0x36 ^ ctx->key[i];
|
||||
EVP_DigestInit_ex(&ctx->i_ctx, md, impl);
|
||||
EVP_DigestUpdate(&ctx->i_ctx, pad, M_EVP_MD_block_size(md));
|
||||
|
||||
for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++)
|
||||
pad[i] = 0x5c ^ ctx->key[i];
|
||||
EVP_DigestInit_ex(&ctx->o_ctx, md, impl);
|
||||
EVP_DigestUpdate(&ctx->o_ctx, pad, M_EVP_MD_block_size(md));
|
||||
}
|
||||
EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx);
|
||||
}
|
||||
|
||||
void HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md)
|
||||
{
|
||||
if (key && md)
|
||||
HMAC_CTX_init(ctx);
|
||||
HMAC_Init_ex(ctx, key, len, md, NULL);
|
||||
}
|
||||
|
||||
void HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
|
||||
{
|
||||
EVP_DigestUpdate(&ctx->md_ctx, data, len);
|
||||
}
|
||||
|
||||
void HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
|
||||
{
|
||||
int j;
|
||||
unsigned int i;
|
||||
unsigned char buf[EVP_MAX_MD_SIZE];
|
||||
|
||||
j = M_EVP_MD_block_size(ctx->md);
|
||||
|
||||
EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i);
|
||||
EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx);
|
||||
EVP_DigestUpdate(&ctx->md_ctx, buf, i);
|
||||
EVP_DigestFinal_ex(&ctx->md_ctx, md, len);
|
||||
}
|
||||
|
||||
void HMAC_CTX_init(HMAC_CTX *ctx)
|
||||
{
|
||||
EVP_MD_CTX_init(&ctx->i_ctx);
|
||||
EVP_MD_CTX_init(&ctx->o_ctx);
|
||||
EVP_MD_CTX_init(&ctx->md_ctx);
|
||||
}
|
||||
|
||||
void HMAC_CTX_cleanup(HMAC_CTX *ctx)
|
||||
{
|
||||
EVP_MD_CTX_cleanup(&ctx->i_ctx);
|
||||
EVP_MD_CTX_cleanup(&ctx->o_ctx);
|
||||
EVP_MD_CTX_cleanup(&ctx->md_ctx);
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
}
|
||||
|
||||
unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
|
||||
const unsigned char *d, size_t n, unsigned char *md,
|
||||
unsigned int *md_len)
|
||||
{
|
||||
HMAC_CTX c;
|
||||
static unsigned char m[EVP_MAX_MD_SIZE];
|
||||
|
||||
if (md == NULL)
|
||||
md = m;
|
||||
HMAC_CTX_init(&c);
|
||||
HMAC_Init(&c, key, key_len, evp_md);
|
||||
HMAC_Update(&c, d, n);
|
||||
HMAC_Final(&c, md, md_len);
|
||||
HMAC_CTX_cleanup(&c);
|
||||
return (md);
|
||||
}
|
||||
|
||||
void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
|
||||
{
|
||||
M_EVP_MD_CTX_set_flags(&ctx->i_ctx, flags);
|
||||
M_EVP_MD_CTX_set_flags(&ctx->o_ctx, flags);
|
||||
M_EVP_MD_CTX_set_flags(&ctx->md_ctx, flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,134 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
typedef struct {
|
||||
const EVP_MD *(*alg) (void);
|
||||
const char *key, *iv;
|
||||
unsigned char kaval[EVP_MAX_MD_SIZE];
|
||||
} HMAC_KAT;
|
||||
|
||||
static const HMAC_KAT vector[] = {
|
||||
{EVP_sha1,
|
||||
/*
|
||||
* from http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
|
||||
*/
|
||||
"0123456789:;<=>?@ABC",
|
||||
"Sample #2",
|
||||
{0x09, 0x22, 0xd3, 0x40, 0x5f, 0xaa, 0x3d, 0x19,
|
||||
0x4f, 0x82, 0xa4, 0x58, 0x30, 0x73, 0x7d, 0x5c,
|
||||
0xc6, 0xc7, 0x5d, 0x24}
|
||||
},
|
||||
{EVP_sha224,
|
||||
/* just keep extending the above... */
|
||||
"0123456789:;<=>?@ABC",
|
||||
"Sample #2",
|
||||
{0xdd, 0xef, 0x0a, 0x40, 0xcb, 0x7d, 0x50, 0xfb,
|
||||
0x6e, 0xe6, 0xce, 0xa1, 0x20, 0xba, 0x26, 0xaa,
|
||||
0x08, 0xf3, 0x07, 0x75, 0x87, 0xb8, 0xad, 0x1b,
|
||||
0x8c, 0x8d, 0x12, 0xc7}
|
||||
},
|
||||
{EVP_sha256,
|
||||
"0123456789:;<=>?@ABC",
|
||||
"Sample #2",
|
||||
{0xb8, 0xf2, 0x0d, 0xb5, 0x41, 0xea, 0x43, 0x09,
|
||||
0xca, 0x4e, 0xa9, 0x38, 0x0c, 0xd0, 0xe8, 0x34,
|
||||
0xf7, 0x1f, 0xbe, 0x91, 0x74, 0xa2, 0x61, 0x38,
|
||||
0x0d, 0xc1, 0x7e, 0xae, 0x6a, 0x34, 0x51, 0xd9}
|
||||
},
|
||||
{EVP_sha384,
|
||||
"0123456789:;<=>?@ABC",
|
||||
"Sample #2",
|
||||
{0x08, 0xbc, 0xb0, 0xda, 0x49, 0x1e, 0x87, 0xad,
|
||||
0x9a, 0x1d, 0x6a, 0xce, 0x23, 0xc5, 0x0b, 0xf6,
|
||||
0xb7, 0x18, 0x06, 0xa5, 0x77, 0xcd, 0x49, 0x04,
|
||||
0x89, 0xf1, 0xe6, 0x23, 0x44, 0x51, 0x51, 0x9f,
|
||||
0x85, 0x56, 0x80, 0x79, 0x0c, 0xbd, 0x4d, 0x50,
|
||||
0xa4, 0x5f, 0x29, 0xe3, 0x93, 0xf0, 0xe8, 0x7f}
|
||||
},
|
||||
{EVP_sha512,
|
||||
"0123456789:;<=>?@ABC",
|
||||
"Sample #2",
|
||||
{0x80, 0x9d, 0x44, 0x05, 0x7c, 0x5b, 0x95, 0x41,
|
||||
0x05, 0xbd, 0x04, 0x13, 0x16, 0xdb, 0x0f, 0xac,
|
||||
0x44, 0xd5, 0xa4, 0xd5, 0xd0, 0x89, 0x2b, 0xd0,
|
||||
0x4e, 0x86, 0x64, 0x12, 0xc0, 0x90, 0x77, 0x68,
|
||||
0xf1, 0x87, 0xb7, 0x7c, 0x4f, 0xae, 0x2c, 0x2f,
|
||||
0x21, 0xa5, 0xb5, 0x65, 0x9a, 0x4f, 0x4b, 0xa7,
|
||||
0x47, 0x02, 0xa3, 0xde, 0x9b, 0x51, 0xf1, 0x45,
|
||||
0xbd, 0x4f, 0x25, 0x27, 0x42, 0x98, 0x99, 0x05}
|
||||
},
|
||||
};
|
||||
|
||||
int FIPS_selftest_hmac()
|
||||
{
|
||||
size_t n;
|
||||
unsigned int outlen;
|
||||
unsigned char out[EVP_MAX_MD_SIZE];
|
||||
const EVP_MD *md;
|
||||
const HMAC_KAT *t;
|
||||
|
||||
for (n = 0, t = vector; n < sizeof(vector) / sizeof(vector[0]); n++, t++) {
|
||||
md = (*t->alg) ();
|
||||
HMAC(md, t->key, strlen(t->key),
|
||||
(const unsigned char *)t->iv, strlen(t->iv), out, &outlen);
|
||||
|
||||
if (memcmp(out, t->kaval, outlen)) {
|
||||
FIPSerr(FIPS_F_FIPS_SELFTEST_HMAC, FIPS_R_SELFTEST_FAILED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,393 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a FIPS approved AES PRNG based on ANSI X9.31 A.2.4.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "e_os.h"
|
||||
|
||||
/*
|
||||
* If we don't define _XOPEN_SOURCE_EXTENDED, struct timeval won't be defined
|
||||
* and gettimeofday() won't be declared with strict compilers like DEC C in
|
||||
* ANSI C mode.
|
||||
*/
|
||||
#ifndef _XOPEN_SOURCE_EXTENDED
|
||||
# define _XOPEN_SOURCE_EXTENDED 1
|
||||
#endif
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips_rand.h>
|
||||
#ifndef OPENSSL_SYS_WIN32
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#ifndef OPENSSL_SYS_WIN32
|
||||
# ifdef OPENSSL_UNISTD
|
||||
# include OPENSSL_UNISTD
|
||||
# else
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <openssl/fips.h>
|
||||
#include "fips_locl.h"
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
void *OPENSSL_stderr(void);
|
||||
|
||||
# define AES_BLOCK_LENGTH 16
|
||||
|
||||
/* AES FIPS PRNG implementation */
|
||||
|
||||
typedef struct {
|
||||
int seeded;
|
||||
int keyed;
|
||||
int test_mode;
|
||||
int second;
|
||||
int error;
|
||||
unsigned long counter;
|
||||
AES_KEY ks;
|
||||
int vpos;
|
||||
/* Temporary storage for key if it equals seed length */
|
||||
unsigned char tmp_key[AES_BLOCK_LENGTH];
|
||||
unsigned char V[AES_BLOCK_LENGTH];
|
||||
unsigned char DT[AES_BLOCK_LENGTH];
|
||||
unsigned char last[AES_BLOCK_LENGTH];
|
||||
} FIPS_PRNG_CTX;
|
||||
|
||||
static FIPS_PRNG_CTX sctx;
|
||||
|
||||
static int fips_prng_fail = 0;
|
||||
|
||||
void FIPS_rng_stick(void)
|
||||
{
|
||||
fips_prng_fail = 1;
|
||||
}
|
||||
|
||||
static void fips_rand_prng_reset(FIPS_PRNG_CTX * ctx)
|
||||
{
|
||||
ctx->seeded = 0;
|
||||
ctx->keyed = 0;
|
||||
ctx->test_mode = 0;
|
||||
ctx->counter = 0;
|
||||
ctx->second = 0;
|
||||
ctx->error = 0;
|
||||
ctx->vpos = 0;
|
||||
OPENSSL_cleanse(ctx->V, AES_BLOCK_LENGTH);
|
||||
OPENSSL_cleanse(&ctx->ks, sizeof(AES_KEY));
|
||||
}
|
||||
|
||||
static int fips_set_prng_key(FIPS_PRNG_CTX * ctx,
|
||||
const unsigned char *key,
|
||||
FIPS_RAND_SIZE_T keylen)
|
||||
{
|
||||
FIPS_selftest_check();
|
||||
if (keylen != 16 && keylen != 24 && keylen != 32) {
|
||||
/* error: invalid key size */
|
||||
return 0;
|
||||
}
|
||||
AES_set_encrypt_key(key, keylen << 3, &ctx->ks);
|
||||
if (keylen == 16) {
|
||||
memcpy(ctx->tmp_key, key, 16);
|
||||
ctx->keyed = 2;
|
||||
} else
|
||||
ctx->keyed = 1;
|
||||
ctx->seeded = 0;
|
||||
ctx->second = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fips_set_prng_seed(FIPS_PRNG_CTX * ctx,
|
||||
const unsigned char *seed,
|
||||
FIPS_RAND_SIZE_T seedlen)
|
||||
{
|
||||
int i;
|
||||
if (!ctx->keyed)
|
||||
return 0;
|
||||
/* In test mode seed is just supplied data */
|
||||
if (ctx->test_mode) {
|
||||
if (seedlen != AES_BLOCK_LENGTH)
|
||||
return 0;
|
||||
memcpy(ctx->V, seed, AES_BLOCK_LENGTH);
|
||||
ctx->seeded = 1;
|
||||
return 1;
|
||||
}
|
||||
/* Outside test mode XOR supplied data with existing seed */
|
||||
for (i = 0; i < seedlen; i++) {
|
||||
ctx->V[ctx->vpos++] ^= seed[i];
|
||||
if (ctx->vpos == AES_BLOCK_LENGTH) {
|
||||
ctx->vpos = 0;
|
||||
/*
|
||||
* Special case if first seed and key length equals block size
|
||||
* check key and seed do not match.
|
||||
*/
|
||||
if (ctx->keyed == 2) {
|
||||
if (!memcmp(ctx->tmp_key, ctx->V, 16)) {
|
||||
RANDerr(RAND_F_FIPS_SET_PRNG_SEED,
|
||||
RAND_R_PRNG_SEED_MUST_NOT_MATCH_KEY);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_cleanse(ctx->tmp_key, 16);
|
||||
ctx->keyed = 1;
|
||||
}
|
||||
ctx->seeded = 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fips_set_test_mode(FIPS_PRNG_CTX * ctx)
|
||||
{
|
||||
if (ctx->keyed) {
|
||||
RANDerr(RAND_F_FIPS_SET_TEST_MODE, RAND_R_PRNG_KEYED);
|
||||
return 0;
|
||||
}
|
||||
ctx->test_mode = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FIPS_rand_test_mode(void)
|
||||
{
|
||||
return fips_set_test_mode(&sctx);
|
||||
}
|
||||
|
||||
int FIPS_rand_set_dt(unsigned char *dt)
|
||||
{
|
||||
if (!sctx.test_mode) {
|
||||
RANDerr(RAND_F_FIPS_RAND_SET_DT, RAND_R_NOT_IN_TEST_MODE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(sctx.DT, dt, AES_BLOCK_LENGTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void fips_get_dt(FIPS_PRNG_CTX * ctx)
|
||||
{
|
||||
# ifdef OPENSSL_SYS_WIN32
|
||||
FILETIME ft;
|
||||
# else
|
||||
struct timeval tv;
|
||||
# endif
|
||||
unsigned char *buf = ctx->DT;
|
||||
|
||||
# ifndef GETPID_IS_MEANINGLESS
|
||||
unsigned long pid;
|
||||
# endif
|
||||
|
||||
# ifdef OPENSSL_SYS_WIN32
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
buf[0] = (unsigned char)(ft.dwHighDateTime & 0xff);
|
||||
buf[1] = (unsigned char)((ft.dwHighDateTime >> 8) & 0xff);
|
||||
buf[2] = (unsigned char)((ft.dwHighDateTime >> 16) & 0xff);
|
||||
buf[3] = (unsigned char)((ft.dwHighDateTime >> 24) & 0xff);
|
||||
buf[4] = (unsigned char)(ft.dwLowDateTime & 0xff);
|
||||
buf[5] = (unsigned char)((ft.dwLowDateTime >> 8) & 0xff);
|
||||
buf[6] = (unsigned char)((ft.dwLowDateTime >> 16) & 0xff);
|
||||
buf[7] = (unsigned char)((ft.dwLowDateTime >> 24) & 0xff);
|
||||
# else
|
||||
gettimeofday(&tv, NULL);
|
||||
buf[0] = (unsigned char)(tv.tv_sec & 0xff);
|
||||
buf[1] = (unsigned char)((tv.tv_sec >> 8) & 0xff);
|
||||
buf[2] = (unsigned char)((tv.tv_sec >> 16) & 0xff);
|
||||
buf[3] = (unsigned char)((tv.tv_sec >> 24) & 0xff);
|
||||
buf[4] = (unsigned char)(tv.tv_usec & 0xff);
|
||||
buf[5] = (unsigned char)((tv.tv_usec >> 8) & 0xff);
|
||||
buf[6] = (unsigned char)((tv.tv_usec >> 16) & 0xff);
|
||||
buf[7] = (unsigned char)((tv.tv_usec >> 24) & 0xff);
|
||||
# endif
|
||||
buf[8] = (unsigned char)(ctx->counter & 0xff);
|
||||
buf[9] = (unsigned char)((ctx->counter >> 8) & 0xff);
|
||||
buf[10] = (unsigned char)((ctx->counter >> 16) & 0xff);
|
||||
buf[11] = (unsigned char)((ctx->counter >> 24) & 0xff);
|
||||
|
||||
ctx->counter++;
|
||||
|
||||
# ifndef GETPID_IS_MEANINGLESS
|
||||
pid = (unsigned long)getpid();
|
||||
buf[12] = (unsigned char)(pid & 0xff);
|
||||
buf[13] = (unsigned char)((pid >> 8) & 0xff);
|
||||
buf[14] = (unsigned char)((pid >> 16) & 0xff);
|
||||
buf[15] = (unsigned char)((pid >> 24) & 0xff);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int fips_rand(FIPS_PRNG_CTX * ctx,
|
||||
unsigned char *out, FIPS_RAND_SIZE_T outlen)
|
||||
{
|
||||
unsigned char R[AES_BLOCK_LENGTH], I[AES_BLOCK_LENGTH];
|
||||
unsigned char tmp[AES_BLOCK_LENGTH];
|
||||
int i;
|
||||
if (ctx->error) {
|
||||
RANDerr(RAND_F_FIPS_RAND, RAND_R_PRNG_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->keyed) {
|
||||
RANDerr(RAND_F_FIPS_RAND, RAND_R_NO_KEY_SET);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->seeded) {
|
||||
RANDerr(RAND_F_FIPS_RAND, RAND_R_PRNG_NOT_SEEDED);
|
||||
return 0;
|
||||
}
|
||||
for (;;) {
|
||||
if (!ctx->test_mode)
|
||||
fips_get_dt(ctx);
|
||||
AES_encrypt(ctx->DT, I, &ctx->ks);
|
||||
for (i = 0; i < AES_BLOCK_LENGTH; i++)
|
||||
tmp[i] = I[i] ^ ctx->V[i];
|
||||
AES_encrypt(tmp, R, &ctx->ks);
|
||||
for (i = 0; i < AES_BLOCK_LENGTH; i++)
|
||||
tmp[i] = R[i] ^ I[i];
|
||||
AES_encrypt(tmp, ctx->V, &ctx->ks);
|
||||
/* Continuous PRNG test */
|
||||
if (ctx->second) {
|
||||
if (fips_prng_fail)
|
||||
memcpy(ctx->last, R, AES_BLOCK_LENGTH);
|
||||
if (!memcmp(R, ctx->last, AES_BLOCK_LENGTH)) {
|
||||
RANDerr(RAND_F_FIPS_RAND, RAND_R_PRNG_STUCK);
|
||||
ctx->error = 1;
|
||||
fips_set_selftest_fail();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memcpy(ctx->last, R, AES_BLOCK_LENGTH);
|
||||
if (!ctx->second) {
|
||||
ctx->second = 1;
|
||||
if (!ctx->test_mode)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outlen <= AES_BLOCK_LENGTH) {
|
||||
memcpy(out, R, outlen);
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(out, R, AES_BLOCK_LENGTH);
|
||||
out += AES_BLOCK_LENGTH;
|
||||
outlen -= AES_BLOCK_LENGTH;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FIPS_rand_set_key(const unsigned char *key, FIPS_RAND_SIZE_T keylen)
|
||||
{
|
||||
int ret;
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
|
||||
ret = fips_set_prng_key(&sctx, key, keylen);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FIPS_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
|
||||
{
|
||||
int ret;
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
|
||||
ret = fips_set_prng_seed(&sctx, seed, seedlen);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FIPS_rand_bytes(unsigned char *out, FIPS_RAND_SIZE_T count)
|
||||
{
|
||||
int ret;
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
|
||||
ret = fips_rand(&sctx, out, count);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FIPS_rand_status(void)
|
||||
{
|
||||
int ret;
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_RAND);
|
||||
ret = sctx.seeded;
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FIPS_rand_reset(void)
|
||||
{
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
|
||||
fips_rand_prng_reset(&sctx);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
|
||||
}
|
||||
|
||||
static void fips_do_rand_seed(const void *seed, FIPS_RAND_SIZE_T seedlen)
|
||||
{
|
||||
FIPS_rand_seed(seed, seedlen);
|
||||
}
|
||||
|
||||
static void fips_do_rand_add(const void *seed, FIPS_RAND_SIZE_T seedlen,
|
||||
double add_entropy)
|
||||
{
|
||||
FIPS_rand_seed(seed, seedlen);
|
||||
}
|
||||
|
||||
static const RAND_METHOD rand_fips_meth = {
|
||||
fips_do_rand_seed,
|
||||
FIPS_rand_bytes,
|
||||
FIPS_rand_reset,
|
||||
fips_do_rand_add,
|
||||
FIPS_rand_bytes,
|
||||
FIPS_rand_status
|
||||
};
|
||||
|
||||
const RAND_METHOD *FIPS_rand_method(void)
|
||||
{
|
||||
return &rand_fips_meth;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,366 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/fips_rand.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
typedef struct {
|
||||
unsigned char DT[16];
|
||||
unsigned char V[16];
|
||||
unsigned char R[16];
|
||||
} AES_PRNG_TV;
|
||||
|
||||
/* The following test vectors are taken directly from the RGNVS spec */
|
||||
|
||||
static unsigned char aes_128_key[16] =
|
||||
{ 0xf3, 0xb1, 0x66, 0x6d, 0x13, 0x60, 0x72, 0x42,
|
||||
0xed, 0x06, 0x1c, 0xab, 0xb8, 0xd4, 0x62, 0x02
|
||||
};
|
||||
|
||||
static AES_PRNG_TV aes_128_tv[] = {
|
||||
{
|
||||
/* DT */
|
||||
{0xe6, 0xb3, 0xbe, 0x78, 0x2a, 0x23, 0xfa, 0x62,
|
||||
0xd7, 0x1d, 0x4a, 0xfb, 0xb0, 0xe9, 0x22, 0xf9},
|
||||
/* V */
|
||||
{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x59, 0x53, 0x1e, 0xd1, 0x3b, 0xb0, 0xc0, 0x55,
|
||||
0x84, 0x79, 0x66, 0x85, 0xc1, 0x2f, 0x76, 0x41}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xe6, 0xb3, 0xbe, 0x78, 0x2a, 0x23, 0xfa, 0x62,
|
||||
0xd7, 0x1d, 0x4a, 0xfb, 0xb0, 0xe9, 0x22, 0xfa},
|
||||
/* V */
|
||||
{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x7c, 0x22, 0x2c, 0xf4, 0xca, 0x8f, 0xa2, 0x4c,
|
||||
0x1c, 0x9c, 0xb6, 0x41, 0xa9, 0xf3, 0x22, 0x0d}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xe6, 0xb3, 0xbe, 0x78, 0x2a, 0x23, 0xfa, 0x62,
|
||||
0xd7, 0x1d, 0x4a, 0xfb, 0xb0, 0xe9, 0x22, 0xfb},
|
||||
/* V */
|
||||
{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x8a, 0xaa, 0x00, 0x39, 0x66, 0x67, 0x5b, 0xe5,
|
||||
0x29, 0x14, 0x28, 0x81, 0xa9, 0x4d, 0x4e, 0xc7}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xe6, 0xb3, 0xbe, 0x78, 0x2a, 0x23, 0xfa, 0x62,
|
||||
0xd7, 0x1d, 0x4a, 0xfb, 0xb0, 0xe9, 0x22, 0xfc},
|
||||
/* V */
|
||||
{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x88, 0xdd, 0xa4, 0x56, 0x30, 0x24, 0x23, 0xe5,
|
||||
0xf6, 0x9d, 0xa5, 0x7e, 0x7b, 0x95, 0xc7, 0x3a}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xe6, 0xb3, 0xbe, 0x78, 0x2a, 0x23, 0xfa, 0x62,
|
||||
0xd7, 0x1d, 0x4a, 0xfb, 0xb0, 0xe9, 0x22, 0xfd},
|
||||
/* V */
|
||||
{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x05, 0x25, 0x92, 0x46, 0x61, 0x79, 0xd2, 0xcb,
|
||||
0x78, 0xc4, 0x0b, 0x14, 0x0a, 0x5a, 0x9a, 0xc8}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xe6, 0xb3, 0xbe, 0x78, 0x2a, 0x23, 0xfa, 0x62,
|
||||
0xd7, 0x1d, 0x4a, 0xfb, 0xb0, 0xe9, 0x23, 0x77},
|
||||
/* V */
|
||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe},
|
||||
/* R */
|
||||
{0x0d, 0xd5, 0xa0, 0x36, 0x7a, 0x59, 0x26, 0xbc,
|
||||
0x48, 0xd9, 0x38, 0xbf, 0xf0, 0x85, 0x8f, 0xea}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xe6, 0xb3, 0xbe, 0x78, 0x2a, 0x23, 0xfa, 0x62,
|
||||
0xd7, 0x1d, 0x4a, 0xfb, 0xb0, 0xe9, 0x23, 0x78},
|
||||
/* V */
|
||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
/* R */
|
||||
{0xae, 0x53, 0x87, 0xee, 0x8c, 0xd9, 0x12, 0xf5,
|
||||
0x73, 0x53, 0xae, 0x03, 0xf9, 0xd5, 0x13, 0x33}
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned char aes_192_key[24] =
|
||||
{ 0x15, 0xd8, 0x78, 0x0d, 0x62, 0xd3, 0x25, 0x6e,
|
||||
0x44, 0x64, 0x10, 0x13, 0x60, 0x2b, 0xa9, 0xbc,
|
||||
0x4a, 0xfb, 0xca, 0xeb, 0x4c, 0x8b, 0x99, 0x3b
|
||||
};
|
||||
|
||||
static AES_PRNG_TV aes_192_tv[] = {
|
||||
{
|
||||
/* DT */
|
||||
{0x3f, 0xd8, 0xff, 0xe8, 0x80, 0x69, 0x8b, 0xc1,
|
||||
0xbf, 0x99, 0x7d, 0xa4, 0x24, 0x78, 0xf3, 0x4b},
|
||||
/* V */
|
||||
{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x17, 0x07, 0xd5, 0x28, 0x19, 0x79, 0x1e, 0xef,
|
||||
0xa5, 0x0c, 0xbf, 0x25, 0xe5, 0x56, 0xb4, 0x93}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0x3f, 0xd8, 0xff, 0xe8, 0x80, 0x69, 0x8b, 0xc1,
|
||||
0xbf, 0x99, 0x7d, 0xa4, 0x24, 0x78, 0xf3, 0x4c},
|
||||
/* V */
|
||||
{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x92, 0x8d, 0xbe, 0x07, 0xdd, 0xc7, 0x58, 0xc0,
|
||||
0x6f, 0x35, 0x41, 0x9b, 0x17, 0xc9, 0xbd, 0x9b}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0x3f, 0xd8, 0xff, 0xe8, 0x80, 0x69, 0x8b, 0xc1,
|
||||
0xbf, 0x99, 0x7d, 0xa4, 0x24, 0x78, 0xf3, 0x4d},
|
||||
/* V */
|
||||
{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0xd5, 0xde, 0xf4, 0x50, 0xf3, 0xb7, 0x10, 0x4e,
|
||||
0xb8, 0xc6, 0xf8, 0xcf, 0xe2, 0xb1, 0xca, 0xa2}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0x3f, 0xd8, 0xff, 0xe8, 0x80, 0x69, 0x8b, 0xc1,
|
||||
0xbf, 0x99, 0x7d, 0xa4, 0x24, 0x78, 0xf3, 0x4e},
|
||||
/* V */
|
||||
{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0xce, 0x29, 0x08, 0x43, 0xfc, 0x34, 0x41, 0xe7,
|
||||
0x47, 0x8f, 0xb3, 0x66, 0x2b, 0x46, 0xb1, 0xbb}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0x3f, 0xd8, 0xff, 0xe8, 0x80, 0x69, 0x8b, 0xc1,
|
||||
0xbf, 0x99, 0x7d, 0xa4, 0x24, 0x78, 0xf3, 0x4f},
|
||||
/* V */
|
||||
{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0xb3, 0x26, 0x0f, 0xf5, 0xd6, 0xca, 0xa8, 0xbf,
|
||||
0x89, 0xb8, 0x5e, 0x2f, 0x22, 0x56, 0x92, 0x2f}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0x3f, 0xd8, 0xff, 0xe8, 0x80, 0x69, 0x8b, 0xc1,
|
||||
0xbf, 0x99, 0x7d, 0xa4, 0x24, 0x78, 0xf3, 0xc9},
|
||||
/* V */
|
||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe},
|
||||
/* R */
|
||||
{0x05, 0xeb, 0x18, 0x52, 0x34, 0x43, 0x00, 0x43,
|
||||
0x6e, 0x5a, 0xa5, 0xfe, 0x7b, 0x32, 0xc4, 0x2d}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0x3f, 0xd8, 0xff, 0xe8, 0x80, 0x69, 0x8b, 0xc1,
|
||||
0xbf, 0x99, 0x7d, 0xa4, 0x24, 0x78, 0xf3, 0xca},
|
||||
/* V */
|
||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
/* R */
|
||||
{0x15, 0x3c, 0xe8, 0xd1, 0x04, 0xc7, 0xad, 0x50,
|
||||
0x0b, 0xf0, 0x07, 0x16, 0xe7, 0x56, 0x7a, 0xea}
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned char aes_256_key[32] =
|
||||
{ 0x6d, 0x14, 0x06, 0x6c, 0xb6, 0xd8, 0x21, 0x2d,
|
||||
0x82, 0x8d, 0xfa, 0xf2, 0x7a, 0x03, 0xb7, 0x9f,
|
||||
0x0c, 0xc7, 0x3e, 0xcd, 0x76, 0xeb, 0xee, 0xb5,
|
||||
0x21, 0x05, 0x8c, 0x4f, 0x31, 0x7a, 0x80, 0xbb
|
||||
};
|
||||
|
||||
static AES_PRNG_TV aes_256_tv[] = {
|
||||
{
|
||||
/* DT */
|
||||
{0xda, 0x3a, 0x41, 0xec, 0x1d, 0xa3, 0xb0, 0xd5,
|
||||
0xf2, 0xa9, 0x4e, 0x34, 0x74, 0x8e, 0x9e, 0x88},
|
||||
/* V */
|
||||
{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x35, 0xc7, 0xef, 0xa7, 0x78, 0x4d, 0x29, 0xbc,
|
||||
0x82, 0x79, 0x99, 0xfb, 0xd0, 0xb3, 0x3b, 0x72}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xda, 0x3a, 0x41, 0xec, 0x1d, 0xa3, 0xb0, 0xd5,
|
||||
0xf2, 0xa9, 0x4e, 0x34, 0x74, 0x8e, 0x9e, 0x89},
|
||||
/* V */
|
||||
{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x6c, 0xf4, 0x42, 0x5d, 0xc7, 0x04, 0x1a, 0x41,
|
||||
0x28, 0x2a, 0x78, 0xa9, 0xb0, 0x12, 0xc4, 0x95}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xda, 0x3a, 0x41, 0xec, 0x1d, 0xa3, 0xb0, 0xd5,
|
||||
0xf2, 0xa9, 0x4e, 0x34, 0x74, 0x8e, 0x9e, 0x8a},
|
||||
/* V */
|
||||
{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x16, 0x90, 0xa4, 0xff, 0x7b, 0x7e, 0xb9, 0x30,
|
||||
0xdb, 0x67, 0x4b, 0xac, 0x2d, 0xe1, 0xd1, 0x75}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xda, 0x3a, 0x41, 0xec, 0x1d, 0xa3, 0xb0, 0xd5,
|
||||
0xf2, 0xa9, 0x4e, 0x34, 0x74, 0x8e, 0x9e, 0x8b},
|
||||
/* V */
|
||||
{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x14, 0x6f, 0xf5, 0x95, 0xa1, 0x46, 0x65, 0x30,
|
||||
0xbc, 0x57, 0xe2, 0x4a, 0xf7, 0x45, 0x62, 0x05}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xda, 0x3a, 0x41, 0xec, 0x1d, 0xa3, 0xb0, 0xd5,
|
||||
0xf2, 0xa9, 0x4e, 0x34, 0x74, 0x8e, 0x9e, 0x8c},
|
||||
/* V */
|
||||
{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
/* R */
|
||||
{0x96, 0xe2, 0xb4, 0x1e, 0x66, 0x5e, 0x0f, 0xa4,
|
||||
0xc5, 0xcd, 0xa2, 0x07, 0xcc, 0xb7, 0x94, 0x40}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xda, 0x3a, 0x41, 0xec, 0x1d, 0xa3, 0xb0, 0xd5,
|
||||
0xf2, 0xa9, 0x4e, 0x34, 0x74, 0x8e, 0x9f, 0x06},
|
||||
/* V */
|
||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe},
|
||||
/* R */
|
||||
{0x61, 0xce, 0x1d, 0x6a, 0x48, 0x75, 0x97, 0x28,
|
||||
0x4b, 0x41, 0xde, 0x18, 0x44, 0x4f, 0x56, 0xec}
|
||||
},
|
||||
{
|
||||
/* DT */
|
||||
{0xda, 0x3a, 0x41, 0xec, 0x1d, 0xa3, 0xb0, 0xd5,
|
||||
0xf2, 0xa9, 0x4e, 0x34, 0x74, 0x8e, 0x9f, 0x07},
|
||||
/* V */
|
||||
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
/* R */
|
||||
{0x52, 0x89, 0x59, 0x79, 0x2d, 0xaa, 0x28, 0xb3,
|
||||
0xb0, 0x8a, 0x3e, 0x70, 0xfa, 0x71, 0x59, 0x84}
|
||||
},
|
||||
};
|
||||
|
||||
void FIPS_corrupt_rng()
|
||||
{
|
||||
aes_192_tv[0].V[0]++;
|
||||
}
|
||||
|
||||
# define fips_rand_test(key, tv) \
|
||||
do_rand_test(key, sizeof key, tv, sizeof(tv)/sizeof(AES_PRNG_TV))
|
||||
|
||||
static int do_rand_test(unsigned char *key, int keylen,
|
||||
AES_PRNG_TV * tv, int ntv)
|
||||
{
|
||||
unsigned char R[16];
|
||||
int i;
|
||||
if (!FIPS_rand_set_key(key, keylen))
|
||||
return 0;
|
||||
for (i = 0; i < ntv; i++) {
|
||||
FIPS_rand_seed(tv[i].V, 16);
|
||||
FIPS_rand_set_dt(tv[i].DT);
|
||||
FIPS_rand_bytes(R, 16);
|
||||
if (memcmp(R, tv[i].R, 16))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FIPS_selftest_rng()
|
||||
{
|
||||
FIPS_rand_reset();
|
||||
if (!FIPS_rand_test_mode()) {
|
||||
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG, FIPS_R_SELFTEST_FAILED);
|
||||
return 0;
|
||||
}
|
||||
if (!fips_rand_test(aes_128_key, aes_128_tv)
|
||||
|| !fips_rand_test(aes_192_key, aes_192_tv)
|
||||
|| !fips_rand_test(aes_256_key, aes_256_tv)) {
|
||||
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG, FIPS_R_SELFTEST_FAILED);
|
||||
return 0;
|
||||
}
|
||||
FIPS_rand_reset();
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,913 @@
|
||||
/* crypto/rsa/rsa_eay.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
|
||||
#if !defined(RSA_NULL) && defined(OPENSSL_FIPS)
|
||||
|
||||
static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa,
|
||||
BN_CTX *ctx);
|
||||
static int RSA_eay_init(RSA *rsa);
|
||||
static int RSA_eay_finish(RSA *rsa);
|
||||
static RSA_METHOD rsa_pkcs1_eay_meth = {
|
||||
"Eric Young's PKCS#1 RSA",
|
||||
RSA_eay_public_encrypt,
|
||||
RSA_eay_public_decrypt, /* signature verification */
|
||||
RSA_eay_private_encrypt, /* signing */
|
||||
RSA_eay_private_decrypt,
|
||||
RSA_eay_mod_exp,
|
||||
BN_mod_exp_mont, /* XXX probably we should not use Montgomery
|
||||
* if e == 3 */
|
||||
RSA_eay_init,
|
||||
RSA_eay_finish,
|
||||
RSA_FLAG_FIPS_METHOD, /* flags */
|
||||
NULL,
|
||||
0, /* rsa_sign */
|
||||
0, /* rsa_verify */
|
||||
NULL /* rsa_keygen */
|
||||
};
|
||||
|
||||
const RSA_METHOD *RSA_PKCS1_SSLeay(void)
|
||||
{
|
||||
return (&rsa_pkcs1_eay_meth);
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage example; MONT_HELPER(rsa, bn_ctx, p, rsa->flags &
|
||||
* RSA_FLAG_CACHE_PRIVATE, goto err);
|
||||
*/
|
||||
# define MONT_HELPER(rsa, ctx, m, pre_cond, err_instr) \
|
||||
if ((pre_cond) && ((rsa)->_method_mod_##m == NULL) && \
|
||||
!BN_MONT_CTX_set_locked(&((rsa)->_method_mod_##m), \
|
||||
CRYPTO_LOCK_RSA, \
|
||||
(rsa)->m, (ctx))) \
|
||||
err_instr
|
||||
|
||||
static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_RSA_EAY_PUBLIC_ENCRYPT, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for large moduli, enforce exponent limit */
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
|
||||
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (!f || !ret || !buf) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
|
||||
break;
|
||||
# ifndef OPENSSL_NO_SHA
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
|
||||
break;
|
||||
# endif
|
||||
case RSA_SSLV23_PADDING:
|
||||
i = RSA_padding_add_SSLv23(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
i = RSA_padding_add_none(buf, num, from, flen);
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
|
||||
if (BN_bin2bn(buf, num, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
/* usually the padding functions would catch this */
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* put in leading 0 bytes if the number is less than the length of the
|
||||
* modulus
|
||||
*/
|
||||
j = BN_num_bytes(ret);
|
||||
i = BN_bn2bin(ret, &(to[num - j]));
|
||||
for (k = 0; k < (num - i); k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (buf != NULL) {
|
||||
OPENSSL_cleanse(buf, num);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
|
||||
{
|
||||
BN_BLINDING *ret;
|
||||
int got_write_lock = 0;
|
||||
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_RSA);
|
||||
|
||||
if (rsa->blinding == NULL) {
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
||||
got_write_lock = 1;
|
||||
|
||||
if (rsa->blinding == NULL)
|
||||
rsa->blinding = RSA_setup_blinding(rsa, ctx);
|
||||
}
|
||||
|
||||
ret = rsa->blinding;
|
||||
if (ret == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_BLINDING_get_thread_id(ret) == CRYPTO_thread_id()) {
|
||||
/* rsa->blinding is ours! */
|
||||
|
||||
*local = 1;
|
||||
} else {
|
||||
/* resort to rsa->mt_blinding instead */
|
||||
|
||||
/*
|
||||
* instructs rsa_blinding_convert(), rsa_blinding_invert() that the
|
||||
* BN_BLINDING is shared, meaning that accesses require locks, and
|
||||
* that the blinding factor must be stored outside the BN_BLINDING
|
||||
*/
|
||||
*local = 0;
|
||||
|
||||
if (rsa->mt_blinding == NULL) {
|
||||
if (!got_write_lock) {
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
||||
got_write_lock = 1;
|
||||
}
|
||||
|
||||
if (rsa->mt_blinding == NULL)
|
||||
rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
|
||||
}
|
||||
ret = rsa->mt_blinding;
|
||||
}
|
||||
|
||||
err:
|
||||
if (got_write_lock)
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
|
||||
else
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f,
|
||||
BIGNUM *r, BN_CTX *ctx)
|
||||
{
|
||||
if (local)
|
||||
return BN_BLINDING_convert_ex(f, NULL, b, ctx);
|
||||
else {
|
||||
int ret;
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING);
|
||||
ret = BN_BLINDING_convert_ex(f, r, b, ctx);
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static int rsa_blinding_invert(BN_BLINDING *b, int local, BIGNUM *f,
|
||||
BIGNUM *r, BN_CTX *ctx)
|
||||
{
|
||||
if (local)
|
||||
return BN_BLINDING_invert_ex(f, NULL, b, ctx);
|
||||
else {
|
||||
int ret;
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
|
||||
ret = BN_BLINDING_invert_ex(f, r, b, ctx);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* signing */
|
||||
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret, *br, *res;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_RSA_EAY_PRIVATE_ENCRYPT, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
br = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (!f || !ret || !buf) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_X931_PADDING:
|
||||
i = RSA_padding_add_X931(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
i = RSA_padding_add_none(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_SSLV23_PADDING:
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
|
||||
if (BN_bin2bn(buf, num, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
/* usually the padding functions would catch this */
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
||||
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
|
||||
if (blinding == NULL) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinding != NULL)
|
||||
if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
|
||||
goto err;
|
||||
|
||||
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||
((rsa->p != NULL) &&
|
||||
(rsa->q != NULL) &&
|
||||
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
|
||||
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
BIGNUM local_d;
|
||||
BIGNUM *d = NULL;
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
BN_init(&local_d);
|
||||
d = &local_d;
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
d = rsa->d;
|
||||
|
||||
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC,
|
||||
goto err);
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (blinding)
|
||||
if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
|
||||
goto err;
|
||||
|
||||
if (padding == RSA_X931_PADDING) {
|
||||
BN_sub(f, rsa->n, ret);
|
||||
if (BN_cmp(ret, f))
|
||||
res = f;
|
||||
else
|
||||
res = ret;
|
||||
} else
|
||||
res = ret;
|
||||
|
||||
/*
|
||||
* put in leading 0 bytes if the number is less than the length of the
|
||||
* modulus
|
||||
*/
|
||||
j = BN_num_bytes(res);
|
||||
i = BN_bn2bin(res, &(to[num - j]));
|
||||
for (k = 0; k < (num - i); k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (buf != NULL) {
|
||||
OPENSSL_cleanse(buf, num);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret, *br;
|
||||
int j, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_RSA_EAY_PRIVATE_DECRYPT, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
br = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (!f || !ret || !buf) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This check was for equality but PGP does evil things and chops off the
|
||||
* top '0' bytes
|
||||
*/
|
||||
if (flen > num) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,
|
||||
RSA_R_DATA_GREATER_THAN_MOD_LEN);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* make data into a big number */
|
||||
if (BN_bin2bn(from, (int)flen, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
||||
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
|
||||
if (blinding == NULL) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinding != NULL)
|
||||
if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
|
||||
goto err;
|
||||
|
||||
/* do the decrypt */
|
||||
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||
((rsa->p != NULL) &&
|
||||
(rsa->q != NULL) &&
|
||||
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
|
||||
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
BIGNUM local_d;
|
||||
BIGNUM *d = NULL;
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
d = &local_d;
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
d = rsa->d;
|
||||
|
||||
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC,
|
||||
goto err);
|
||||
if (!rsa->
|
||||
meth->bn_mod_exp(ret, f, d, rsa->n, ctx, rsa->_method_mod_n))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (blinding)
|
||||
if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
|
||||
goto err;
|
||||
|
||||
p = buf;
|
||||
j = BN_bn2bin(ret, p); /* j is only used with no-padding mode */
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
|
||||
break;
|
||||
# ifndef OPENSSL_NO_SHA
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
|
||||
break;
|
||||
# endif
|
||||
case RSA_SSLV23_PADDING:
|
||||
r = RSA_padding_check_SSLv23(to, num, buf, j, num);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, j, num);
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (r < 0)
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
|
||||
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (buf != NULL) {
|
||||
OPENSSL_cleanse(buf, num);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
/* signature verification */
|
||||
static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_RSA_EAY_PUBLIC_DECRYPT, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FIPS_mode()
|
||||
&& (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for large moduli, enforce exponent limit */
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
|
||||
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (!f || !ret || !buf) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This check was for equality but PGP does evil things and chops off the
|
||||
* top '0' bytes
|
||||
*/
|
||||
if (flen > num) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_bin2bn(from, flen, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
|
||||
if ((padding == RSA_X931_PADDING) && ((ret->d[0] & 0xf) != 12))
|
||||
BN_sub(ret, rsa->n, ret);
|
||||
|
||||
p = buf;
|
||||
i = BN_bn2bin(ret, p);
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num);
|
||||
break;
|
||||
case RSA_X931_PADDING:
|
||||
r = RSA_padding_check_X931(to, num, buf, i, num);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, i, num);
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (r < 0)
|
||||
RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
|
||||
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (buf != NULL) {
|
||||
OPENSSL_cleanse(buf, num);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *r1, *m1, *vrfy;
|
||||
BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
|
||||
BIGNUM *dmp1, *dmq1, *c, *pr1;
|
||||
int bn_flags;
|
||||
int ret = 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
r1 = BN_CTX_get(ctx);
|
||||
m1 = BN_CTX_get(ctx);
|
||||
vrfy = BN_CTX_get(ctx);
|
||||
|
||||
/*
|
||||
* Make sure mod_inverse in montgomerey intialization use correct
|
||||
* BN_FLG_CONSTTIME flag.
|
||||
*/
|
||||
bn_flags = rsa->p->flags;
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
rsa->p->flags |= BN_FLG_CONSTTIME;
|
||||
}
|
||||
MONT_HELPER(rsa, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
|
||||
/* We restore bn_flags back */
|
||||
rsa->p->flags = bn_flags;
|
||||
|
||||
/*
|
||||
* Make sure mod_inverse in montgomerey intialization use correct
|
||||
* BN_FLG_CONSTTIME flag.
|
||||
*/
|
||||
bn_flags = rsa->q->flags;
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
rsa->q->flags |= BN_FLG_CONSTTIME;
|
||||
}
|
||||
MONT_HELPER(rsa, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
|
||||
/* We restore bn_flags back */
|
||||
rsa->q->flags = bn_flags;
|
||||
|
||||
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
|
||||
|
||||
/* compute I mod q */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
c = &local_c;
|
||||
BN_with_flags(c, I, BN_FLG_CONSTTIME);
|
||||
if (!BN_mod(r1, c, rsa->q, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mod(r1, I, rsa->q, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* compute r1^dmq1 mod q */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
dmq1 = &local_dmq1;
|
||||
BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
dmq1 = rsa->dmq1;
|
||||
if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q))
|
||||
goto err;
|
||||
|
||||
/* compute I mod p */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
c = &local_c;
|
||||
BN_with_flags(c, I, BN_FLG_CONSTTIME);
|
||||
if (!BN_mod(r1, c, rsa->p, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mod(r1, I, rsa->p, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* compute r1^dmp1 mod p */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
dmp1 = &local_dmp1;
|
||||
BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
dmp1 = rsa->dmp1;
|
||||
if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p))
|
||||
goto err;
|
||||
|
||||
if (!BN_sub(r0, r0, m1))
|
||||
goto err;
|
||||
/*
|
||||
* This will help stop the size of r0 increasing, which does affect the
|
||||
* multiply if it optimised for a power of 2 size
|
||||
*/
|
||||
if (BN_is_negative(r0))
|
||||
if (!BN_add(r0, r0, rsa->p))
|
||||
goto err;
|
||||
|
||||
if (!BN_mul(r1, r0, rsa->iqmp, ctx))
|
||||
goto err;
|
||||
|
||||
/* Turn BN_FLG_CONSTTIME flag on before division operation */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
pr1 = &local_r1;
|
||||
BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
pr1 = r1;
|
||||
if (!BN_mod(r0, pr1, rsa->p, ctx))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If p < q it is occasionally possible for the correction of adding 'p'
|
||||
* if r0 is negative above to leave the result still negative. This can
|
||||
* break the private key operations: the following second correction
|
||||
* should *always* correct this rare occurrence. This will *never* happen
|
||||
* with OpenSSL generated keys because they ensure p > q [steve]
|
||||
*/
|
||||
if (BN_is_negative(r0))
|
||||
if (!BN_add(r0, r0, rsa->p))
|
||||
goto err;
|
||||
if (!BN_mul(r1, r0, rsa->q, ctx))
|
||||
goto err;
|
||||
if (!BN_add(r0, r1, m1))
|
||||
goto err;
|
||||
|
||||
if (rsa->e && rsa->n) {
|
||||
if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
/*
|
||||
* If 'I' was greater than (or equal to) rsa->n, the operation will
|
||||
* be equivalent to using 'I mod n'. However, the result of the
|
||||
* verify will *always* be less than 'n' so we don't check for
|
||||
* absolute equality, just congruency.
|
||||
*/
|
||||
if (!BN_sub(vrfy, vrfy, I))
|
||||
goto err;
|
||||
if (!BN_mod(vrfy, vrfy, rsa->n, ctx))
|
||||
goto err;
|
||||
if (BN_is_negative(vrfy))
|
||||
if (!BN_add(vrfy, vrfy, rsa->n))
|
||||
goto err;
|
||||
if (!BN_is_zero(vrfy)) {
|
||||
/*
|
||||
* 'I' and 'vrfy' aren't congruent mod n. Don't leak
|
||||
* miscalculated CRT output, just do a raw (slower) mod_exp and
|
||||
* return that instead.
|
||||
*/
|
||||
|
||||
BIGNUM local_d;
|
||||
BIGNUM *d = NULL;
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
d = &local_d;
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
d = rsa->d;
|
||||
if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int RSA_eay_init(RSA *rsa)
|
||||
{
|
||||
FIPS_selftest_check();
|
||||
rsa->flags |= RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int RSA_eay_finish(RSA *rsa)
|
||||
{
|
||||
if (rsa->_method_mod_n != NULL)
|
||||
BN_MONT_CTX_free(rsa->_method_mod_n);
|
||||
if (rsa->_method_mod_p != NULL)
|
||||
BN_MONT_CTX_free(rsa->_method_mod_p);
|
||||
if (rsa->_method_mod_q != NULL)
|
||||
BN_MONT_CTX_free(rsa->_method_mod_q);
|
||||
return (1);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,326 @@
|
||||
/* crypto/rsa/rsa_gen.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
/*
|
||||
* NB: these functions have been "upgraded", the deprecated versions (which
|
||||
* are compatibility wrappers using these functions) are in rsa_depr.c. -
|
||||
* Geoff
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/fips.h>
|
||||
#include "fips_locl.h"
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
static int fips_rsa_pairwise_fail = 0;
|
||||
|
||||
void FIPS_corrupt_rsa_keygen(void)
|
||||
{
|
||||
fips_rsa_pairwise_fail = 1;
|
||||
}
|
||||
|
||||
int fips_check_rsa(RSA *rsa)
|
||||
{
|
||||
const unsigned char tbs[] = "RSA Pairwise Check Data";
|
||||
unsigned char *ctbuf = NULL, *ptbuf = NULL;
|
||||
int len, ret = 0;
|
||||
EVP_PKEY pk;
|
||||
pk.type = EVP_PKEY_RSA;
|
||||
pk.pkey.rsa = rsa;
|
||||
|
||||
/* Perform pairwise consistency signature test */
|
||||
if (!fips_pkey_signature_test(&pk, tbs, -1,
|
||||
NULL, 0, EVP_sha1(),
|
||||
EVP_MD_CTX_FLAG_PAD_PKCS1, NULL)
|
||||
|| !fips_pkey_signature_test(&pk, tbs, -1, NULL, 0, EVP_sha1(),
|
||||
EVP_MD_CTX_FLAG_PAD_X931, NULL)
|
||||
|| !fips_pkey_signature_test(&pk, tbs, -1, NULL, 0, EVP_sha1(),
|
||||
EVP_MD_CTX_FLAG_PAD_PSS, NULL))
|
||||
goto err;
|
||||
/* Now perform pairwise consistency encrypt/decrypt test */
|
||||
ctbuf = OPENSSL_malloc(RSA_size(rsa));
|
||||
if (!ctbuf)
|
||||
goto err;
|
||||
|
||||
len =
|
||||
RSA_public_encrypt(sizeof(tbs) - 1, tbs, ctbuf, rsa,
|
||||
RSA_PKCS1_PADDING);
|
||||
if (len <= 0)
|
||||
goto err;
|
||||
/* Check ciphertext doesn't match plaintext */
|
||||
if ((len == (sizeof(tbs) - 1)) && !memcmp(tbs, ctbuf, len))
|
||||
goto err;
|
||||
ptbuf = OPENSSL_malloc(RSA_size(rsa));
|
||||
|
||||
if (!ptbuf)
|
||||
goto err;
|
||||
len = RSA_private_decrypt(len, ctbuf, ptbuf, rsa, RSA_PKCS1_PADDING);
|
||||
if (len != (sizeof(tbs) - 1))
|
||||
goto err;
|
||||
if (memcmp(ptbuf, tbs, len))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
if (!ptbuf)
|
||||
goto err;
|
||||
|
||||
err:
|
||||
if (ret == 0) {
|
||||
fips_set_selftest_fail();
|
||||
FIPSerr(FIPS_F_FIPS_CHECK_RSA, FIPS_R_PAIRWISE_TEST_FAILED);
|
||||
}
|
||||
|
||||
if (ctbuf)
|
||||
OPENSSL_free(ctbuf);
|
||||
if (ptbuf)
|
||||
OPENSSL_free(ptbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
|
||||
BN_GENCB *cb);
|
||||
|
||||
/*
|
||||
* NB: this wrapper would normally be placed in rsa_lib.c and the static
|
||||
* implementation would probably be in rsa_eay.c. Nonetheless, is kept here
|
||||
* so that we don't introduce a new linker dependency. Eg. any application
|
||||
* that wasn't previously linking object code related to key-generation won't
|
||||
* have to now just because key-generation is part of RSA_METHOD.
|
||||
*/
|
||||
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
|
||||
{
|
||||
if (rsa->meth->rsa_keygen)
|
||||
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
|
||||
return rsa_builtin_keygen(rsa, bits, e_value, cb);
|
||||
}
|
||||
|
||||
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
|
||||
BIGNUM local_r0, local_d, local_p;
|
||||
BIGNUM *pr0, *d, *p;
|
||||
int bitsp, bitsq, ok = -1, n = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_RSA_BUILTIN_KEYGEN, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FIPS_mode() && (bits < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS)) {
|
||||
FIPSerr(FIPS_F_RSA_BUILTIN_KEYGEN, FIPS_R_KEY_TOO_SHORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
r0 = BN_CTX_get(ctx);
|
||||
r1 = BN_CTX_get(ctx);
|
||||
r2 = BN_CTX_get(ctx);
|
||||
r3 = BN_CTX_get(ctx);
|
||||
if (r3 == NULL)
|
||||
goto err;
|
||||
|
||||
bitsp = (bits + 1) / 2;
|
||||
bitsq = bits - bitsp;
|
||||
|
||||
/* We need the RSA components non-NULL */
|
||||
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->d && ((rsa->d = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->e && ((rsa->e = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->p && ((rsa->p = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->q && ((rsa->q = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL))
|
||||
goto err;
|
||||
|
||||
BN_copy(rsa->e, e_value);
|
||||
|
||||
/* generate p and q */
|
||||
for (;;) {
|
||||
if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
|
||||
goto err;
|
||||
if (!BN_sub(r2, rsa->p, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_gcd(r1, r2, rsa->e, ctx))
|
||||
goto err;
|
||||
if (BN_is_one(r1))
|
||||
break;
|
||||
if (!BN_GENCB_call(cb, 2, n++))
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
goto err;
|
||||
for (;;) {
|
||||
/*
|
||||
* When generating ridiculously small keys, we can get stuck
|
||||
* continually regenerating the same prime values. Check for this and
|
||||
* bail if it happens 3 times.
|
||||
*/
|
||||
unsigned int degenerate = 0;
|
||||
do {
|
||||
if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb))
|
||||
goto err;
|
||||
} while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
|
||||
if (degenerate == 3) {
|
||||
ok = 0; /* we set our own err */
|
||||
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_gcd(r1, r2, rsa->e, ctx))
|
||||
goto err;
|
||||
if (BN_is_one(r1))
|
||||
break;
|
||||
if (!BN_GENCB_call(cb, 2, n++))
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 3, 1))
|
||||
goto err;
|
||||
if (BN_cmp(rsa->p, rsa->q) < 0) {
|
||||
tmp = rsa->p;
|
||||
rsa->p = rsa->q;
|
||||
rsa->q = tmp;
|
||||
}
|
||||
|
||||
/* calculate n */
|
||||
if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d */
|
||||
if (!BN_sub(r1, rsa->p, BN_value_one()))
|
||||
goto err; /* p-1 */
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one()))
|
||||
goto err; /* q-1 */
|
||||
if (!BN_mul(r0, r1, r2, ctx))
|
||||
goto err; /* (p-1)(q-1) */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
pr0 = &local_r0;
|
||||
BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
pr0 = r0;
|
||||
if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx))
|
||||
goto err; /* d */
|
||||
|
||||
/* set up d for correct BN_FLG_CONSTTIME flag */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
d = &local_d;
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
d = rsa->d;
|
||||
|
||||
/* calculate d mod (p-1) */
|
||||
if (!BN_mod(rsa->dmp1, d, r1, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d mod (q-1) */
|
||||
if (!BN_mod(rsa->dmq1, d, r2, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate inverse of q mod p */
|
||||
if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
|
||||
p = &local_p;
|
||||
BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
|
||||
} else
|
||||
p = rsa->p;
|
||||
if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx))
|
||||
goto err;
|
||||
|
||||
if (fips_rsa_pairwise_fail)
|
||||
BN_add_word(rsa->n, 1);
|
||||
|
||||
if (!fips_check_rsa(rsa))
|
||||
goto err;
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
|
||||
ok = 0;
|
||||
}
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
/* fips_rsa_sign.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2007.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
/*
|
||||
* Minimal FIPS versions of FIPS_rsa_new() and FIPS_rsa_free: to reduce
|
||||
* external dependencies.
|
||||
*/
|
||||
|
||||
RSA *FIPS_rsa_new(void)
|
||||
{
|
||||
RSA *ret;
|
||||
ret = OPENSSL_malloc(sizeof(RSA));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
memset(ret, 0, sizeof(RSA));
|
||||
ret->meth = RSA_PKCS1_SSLeay();
|
||||
if (ret->meth->init)
|
||||
ret->meth->init(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FIPS_rsa_free(RSA *r)
|
||||
{
|
||||
if (!r)
|
||||
return;
|
||||
if (r->meth->finish)
|
||||
r->meth->finish(r);
|
||||
if (r->n != NULL)
|
||||
BN_clear_free(r->n);
|
||||
if (r->e != NULL)
|
||||
BN_clear_free(r->e);
|
||||
if (r->d != NULL)
|
||||
BN_clear_free(r->d);
|
||||
if (r->p != NULL)
|
||||
BN_clear_free(r->p);
|
||||
if (r->q != NULL)
|
||||
BN_clear_free(r->q);
|
||||
if (r->dmp1 != NULL)
|
||||
BN_clear_free(r->dmp1);
|
||||
if (r->dmq1 != NULL)
|
||||
BN_clear_free(r->dmq1);
|
||||
if (r->iqmp != NULL)
|
||||
BN_clear_free(r->iqmp);
|
||||
if (r->blinding != NULL)
|
||||
BN_BLINDING_free(r->blinding);
|
||||
if (r->mt_blinding != NULL)
|
||||
BN_BLINDING_free(r->mt_blinding);
|
||||
if (r->bignum_data != NULL)
|
||||
OPENSSL_free_locked(r->bignum_data);
|
||||
OPENSSL_free(r);
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2003-2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
static unsigned char n[] =
|
||||
"\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71"
|
||||
"\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5"
|
||||
"\x1F\xB8\xDF\xBA\xAF\x03\x5C\x02\xAB\x61\xEA\x48\xCE\xEB\x6F\xCD"
|
||||
"\x48\x76\xED\x52\x0D\x60\xE1\xEC\x46\x19\x71\x9D\x8A\x5B\x8B\x80"
|
||||
"\x7F\xAF\xB8\xE0\xA3\xDF\xC7\x37\x72\x3E\xE6\xB4\xB7\xD9\x3A\x25"
|
||||
"\x84\xEE\x6A\x64\x9D\x06\x09\x53\x74\x88\x34\xB2\x45\x45\x98\x39"
|
||||
"\x4E\xE0\xAA\xB1\x2D\x7B\x61\xA5\x1F\x52\x7A\x9A\x41\xF6\xC1\x68"
|
||||
"\x7F\xE2\x53\x72\x98\xCA\x2A\x8F\x59\x46\xF8\xE5\xFD\x09\x1D\xBD" "\xCB";
|
||||
|
||||
static int setrsakey(RSA *key)
|
||||
{
|
||||
static const unsigned char e[] = "\x11";
|
||||
|
||||
static const unsigned char d[] =
|
||||
"\x00\xA5\xDA\xFC\x53\x41\xFA\xF2\x89\xC4\xB9\x88\xDB\x30\xC1\xCD"
|
||||
"\xF8\x3F\x31\x25\x1E\x06\x68\xB4\x27\x84\x81\x38\x01\x57\x96\x41"
|
||||
"\xB2\x94\x10\xB3\xC7\x99\x8D\x6B\xC4\x65\x74\x5E\x5C\x39\x26\x69"
|
||||
"\xD6\x87\x0D\xA2\xC0\x82\xA9\x39\xE3\x7F\xDC\xB8\x2E\xC9\x3E\xDA"
|
||||
"\xC9\x7F\xF3\xAD\x59\x50\xAC\xCF\xBC\x11\x1C\x76\xF1\xA9\x52\x94"
|
||||
"\x44\xE5\x6A\xAF\x68\xC5\x6C\x09\x2C\xD3\x8D\xC3\xBE\xF5\xD2\x0A"
|
||||
"\x93\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94"
|
||||
"\xAF\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3"
|
||||
"\xC1";
|
||||
|
||||
static const unsigned char p[] =
|
||||
"\x00\xEE\xCF\xAE\x81\xB1\xB9\xB3\xC9\x08\x81\x0B\x10\xA1\xB5\x60"
|
||||
"\x01\x99\xEB\x9F\x44\xAE\xF4\xFD\xA4\x93\xB8\x1A\x9E\x3D\x84\xF6"
|
||||
"\x32\x12\x4E\xF0\x23\x6E\x5D\x1E\x3B\x7E\x28\xFA\xE7\xAA\x04\x0A"
|
||||
"\x2D\x5B\x25\x21\x76\x45\x9D\x1F\x39\x75\x41\xBA\x2A\x58\xFB\x65"
|
||||
"\x99";
|
||||
|
||||
static const unsigned char q[] =
|
||||
"\x00\xC9\x7F\xB1\xF0\x27\xF4\x53\xF6\x34\x12\x33\xEA\xAA\xD1\xD9"
|
||||
"\x35\x3F\x6C\x42\xD0\x88\x66\xB1\xD0\x5A\x0F\x20\x35\x02\x8B\x9D"
|
||||
"\x86\x98\x40\xB4\x16\x66\xB4\x2E\x92\xEA\x0D\xA3\xB4\x32\x04\xB5"
|
||||
"\xCF\xCE\x33\x52\x52\x4D\x04\x16\xA5\xA4\x41\xE7\x00\xAF\x46\x15"
|
||||
"\x03";
|
||||
|
||||
static const unsigned char dmp1[] =
|
||||
"\x54\x49\x4C\xA6\x3E\xBA\x03\x37\xE4\xE2\x40\x23\xFC\xD6\x9A\x5A"
|
||||
"\xEB\x07\xDD\xDC\x01\x83\xA4\xD0\xAC\x9B\x54\xB0\x51\xF2\xB1\x3E"
|
||||
"\xD9\x49\x09\x75\xEA\xB7\x74\x14\xFF\x59\xC1\xF7\x69\x2E\x9A\x2E"
|
||||
"\x20\x2B\x38\xFC\x91\x0A\x47\x41\x74\xAD\xC9\x3C\x1F\x67\xC9\x81";
|
||||
|
||||
static const unsigned char dmq1[] =
|
||||
"\x47\x1E\x02\x90\xFF\x0A\xF0\x75\x03\x51\xB7\xF8\x78\x86\x4C\xA9"
|
||||
"\x61\xAD\xBD\x3A\x8A\x7E\x99\x1C\x5C\x05\x56\xA9\x4C\x31\x46\xA7"
|
||||
"\xF9\x80\x3F\x8F\x6F\x8A\xE3\x42\xE9\x31\xFD\x8A\xE4\x7A\x22\x0D"
|
||||
"\x1B\x99\xA4\x95\x84\x98\x07\xFE\x39\xF9\x24\x5A\x98\x36\xDA\x3D";
|
||||
|
||||
static const unsigned char iqmp[] =
|
||||
"\x00\xB0\x6C\x4F\xDA\xBB\x63\x01\x19\x8D\x26\x5B\xDB\xAE\x94\x23"
|
||||
"\xB3\x80\xF2\x71\xF7\x34\x53\x88\x50\x93\x07\x7F\xCD\x39\xE2\x11"
|
||||
"\x9F\xC9\x86\x32\x15\x4F\x58\x83\xB1\x67\xA9\x67\xBF\x40\x2B\x4E"
|
||||
"\x9E\x2E\x0F\x96\x56\xE6\x98\xEA\x36\x66\xED\xFB\x25\x79\x80\x39"
|
||||
"\xF7";
|
||||
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FIPS_corrupt_rsa()
|
||||
{
|
||||
n[0]++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Known Answer Test (KAT) data for the above RSA private key signing
|
||||
* kat_tbs.
|
||||
*/
|
||||
|
||||
static const unsigned char kat_tbs[] =
|
||||
"OpenSSL FIPS 140-2 Public Key RSA KAT";
|
||||
|
||||
static const unsigned char kat_RSA_PSS_SHA1[] = {
|
||||
0x2D, 0xAF, 0x6E, 0xC2, 0x98, 0xFB, 0x8A, 0xA1, 0xB9, 0x46, 0xDA, 0x0F,
|
||||
0x01, 0x1E, 0x37, 0x93, 0xC2, 0x55, 0x27, 0xE4, 0x1D, 0xD2, 0x90, 0xBB,
|
||||
0xF4, 0xBF, 0x4A, 0x74, 0x39, 0x51, 0xBB, 0xE8, 0x0C, 0xB7, 0xF8, 0xD3,
|
||||
0xD1, 0xDF, 0xE7, 0xBE, 0x80, 0x05, 0xC3, 0xB5, 0xC7, 0x83, 0xD5, 0x4C,
|
||||
0x7F, 0x49, 0xFB, 0x3F, 0x29, 0x9B, 0xE1, 0x12, 0x51, 0x60, 0xD0, 0xA7,
|
||||
0x0D, 0xA9, 0x28, 0x56, 0x73, 0xD9, 0x07, 0xE3, 0x5E, 0x3F, 0x9B, 0xF5,
|
||||
0xB6, 0xF3, 0xF2, 0x5E, 0x74, 0xC9, 0x83, 0x81, 0x47, 0xF0, 0xC5, 0x45,
|
||||
0x0A, 0xE9, 0x8E, 0x38, 0xD7, 0x18, 0xC6, 0x2A, 0x0F, 0xF8, 0xB7, 0x31,
|
||||
0xD6, 0x55, 0xE4, 0x66, 0x78, 0x81, 0xD4, 0xE6, 0xDB, 0x9F, 0xBA, 0xE8,
|
||||
0x23, 0xB5, 0x7F, 0xDC, 0x08, 0xEA, 0xD5, 0x26, 0x1E, 0x20, 0x25, 0x84,
|
||||
0x26, 0xC6, 0x79, 0xC9, 0x9B, 0x3D, 0x7E, 0xA9
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_PSS_SHA224[] = {
|
||||
0x39, 0x4A, 0x6A, 0x20, 0xBC, 0xE9, 0x33, 0xED, 0xEF, 0xC5, 0x58, 0xA7,
|
||||
0xFE, 0x81, 0xC4, 0x36, 0x50, 0x9A, 0x2C, 0x82, 0x98, 0x08, 0x95, 0xFA,
|
||||
0xB1, 0x9E, 0xD2, 0x55, 0x61, 0x87, 0x21, 0x59, 0x87, 0x7B, 0x1F, 0x57,
|
||||
0x30, 0x9D, 0x0D, 0x4A, 0x06, 0xEB, 0x52, 0x37, 0x55, 0x54, 0x1C, 0x89,
|
||||
0x83, 0x75, 0x59, 0x65, 0x64, 0x90, 0x2E, 0x16, 0xCC, 0x86, 0x05, 0xEE,
|
||||
0xB1, 0xE6, 0x7B, 0xBA, 0x16, 0x75, 0x0D, 0x0C, 0x64, 0x0B, 0xAB, 0x22,
|
||||
0x15, 0x78, 0x6B, 0x6F, 0xA4, 0xFB, 0x77, 0x40, 0x64, 0x62, 0xD1, 0xB5,
|
||||
0x37, 0x1E, 0xE0, 0x3D, 0xA8, 0xF9, 0xD2, 0xBD, 0xAA, 0x38, 0x24, 0x49,
|
||||
0x58, 0xD2, 0x74, 0x85, 0xF4, 0xB5, 0x93, 0x8E, 0xF5, 0x03, 0xEA, 0x2D,
|
||||
0xC8, 0x52, 0xFA, 0xCF, 0x7E, 0x35, 0xB0, 0x6A, 0xAF, 0x95, 0xC0, 0x00,
|
||||
0x54, 0x76, 0x3D, 0x0C, 0x9C, 0xB2, 0xEE, 0xC0
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_PSS_SHA256[] = {
|
||||
0x6D, 0x3D, 0xBE, 0x8F, 0x60, 0x6D, 0x25, 0x14, 0xF0, 0x31, 0xE3, 0x89,
|
||||
0x00, 0x97, 0xFA, 0x99, 0x71, 0x28, 0xE5, 0x10, 0x25, 0x9A, 0xF3, 0x8F,
|
||||
0x7B, 0xC5, 0xA8, 0x4A, 0x74, 0x51, 0x36, 0xE2, 0x8D, 0x7D, 0x73, 0x28,
|
||||
0xC1, 0x77, 0xC6, 0x27, 0x97, 0x00, 0x8B, 0x00, 0xA3, 0x96, 0x73, 0x4E,
|
||||
0x7D, 0x2E, 0x2C, 0x34, 0x68, 0x8C, 0x8E, 0xDF, 0x9D, 0x49, 0x47, 0x05,
|
||||
0xAB, 0xF5, 0x01, 0xD6, 0x81, 0x47, 0x70, 0xF5, 0x1D, 0x6D, 0x26, 0xBA,
|
||||
0x2F, 0x7A, 0x54, 0x53, 0x4E, 0xED, 0x71, 0xD9, 0x5A, 0xF3, 0xDA, 0xB6,
|
||||
0x0B, 0x47, 0x34, 0xAF, 0x90, 0xDC, 0xC8, 0xD9, 0x6F, 0x56, 0xCD, 0x9F,
|
||||
0x21, 0xB7, 0x7E, 0xAD, 0x7C, 0x2F, 0x75, 0x50, 0x47, 0x12, 0xE4, 0x6D,
|
||||
0x5F, 0xB7, 0x01, 0xDF, 0xC3, 0x11, 0x6C, 0xA9, 0x9E, 0x49, 0xB9, 0xF6,
|
||||
0x72, 0xF4, 0xF6, 0xEF, 0x88, 0x1E, 0x2D, 0x1C
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_PSS_SHA384[] = {
|
||||
0x40, 0xFB, 0xA1, 0x21, 0xF4, 0xB2, 0x40, 0x9A, 0xB4, 0x31, 0xA8, 0xF2,
|
||||
0xEC, 0x1C, 0xC4, 0xC8, 0x7C, 0x22, 0x65, 0x9C, 0x57, 0x45, 0xCD, 0x5E,
|
||||
0x86, 0x00, 0xF7, 0x25, 0x78, 0xDE, 0xDC, 0x7A, 0x71, 0x44, 0x9A, 0xCD,
|
||||
0xAA, 0x25, 0xF4, 0xB2, 0xFC, 0xF0, 0x75, 0xD9, 0x2F, 0x78, 0x23, 0x7F,
|
||||
0x6F, 0x02, 0xEF, 0xC1, 0xAF, 0xA6, 0x28, 0x16, 0x31, 0xDC, 0x42, 0x6C,
|
||||
0xB2, 0x44, 0xE5, 0x4D, 0x66, 0xA2, 0xE6, 0x71, 0xF3, 0xAC, 0x4F, 0xFB,
|
||||
0x91, 0xCA, 0xF5, 0x70, 0xEF, 0x6B, 0x9D, 0xA4, 0xEF, 0xD9, 0x3D, 0x2F,
|
||||
0x3A, 0xBE, 0x89, 0x38, 0x59, 0x01, 0xBA, 0xDA, 0x32, 0xAD, 0x42, 0x89,
|
||||
0x98, 0x8B, 0x39, 0x44, 0xF0, 0xFC, 0x38, 0xAC, 0x87, 0x1F, 0xCA, 0x6F,
|
||||
0x48, 0xF6, 0xAE, 0xD7, 0x45, 0xEE, 0xAE, 0x88, 0x0E, 0x60, 0xF4, 0x55,
|
||||
0x48, 0x44, 0xEE, 0x1F, 0x90, 0x18, 0x4B, 0xF1
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_PSS_SHA512[] = {
|
||||
0x07, 0x1E, 0xD8, 0xD5, 0x05, 0xE8, 0xE6, 0xE6, 0x57, 0xAE, 0x63, 0x8C,
|
||||
0xC6, 0x83, 0xB7, 0xA0, 0x59, 0xBB, 0xF2, 0xC6, 0x8F, 0x12, 0x53, 0x9A,
|
||||
0x9B, 0x54, 0x9E, 0xB3, 0xC1, 0x1D, 0x23, 0x4D, 0x51, 0xED, 0x9E, 0xDD,
|
||||
0x4B, 0xF3, 0x46, 0x9B, 0x6B, 0xF6, 0x7C, 0x24, 0x60, 0x79, 0x23, 0x39,
|
||||
0x01, 0x1C, 0x51, 0xCB, 0xD8, 0xE9, 0x9A, 0x01, 0x67, 0x5F, 0xFE, 0xD7,
|
||||
0x7C, 0xE3, 0x7F, 0xED, 0xDB, 0x87, 0xBB, 0xF0, 0x3D, 0x78, 0x55, 0x61,
|
||||
0x57, 0xE3, 0x0F, 0xE3, 0xD2, 0x9D, 0x0C, 0x2A, 0x20, 0xB0, 0x85, 0x13,
|
||||
0xC5, 0x47, 0x34, 0x0D, 0x32, 0x15, 0xC8, 0xAE, 0x9A, 0x6A, 0x39, 0x63,
|
||||
0x2D, 0x60, 0xF5, 0x4C, 0xDF, 0x8A, 0x48, 0x4B, 0xBF, 0xF4, 0xA8, 0xFE,
|
||||
0x76, 0xF2, 0x32, 0x1B, 0x9C, 0x7C, 0xCA, 0xFE, 0x7F, 0x80, 0xC2, 0x88,
|
||||
0x5C, 0x97, 0x70, 0xB4, 0x26, 0xC9, 0x14, 0x8B
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_SHA1[] = {
|
||||
0x71, 0xEE, 0x1A, 0xC0, 0xFE, 0x01, 0x93, 0x54, 0x79, 0x5C, 0xF2, 0x4C,
|
||||
0x4A, 0xFD, 0x1A, 0x05, 0x8F, 0x64, 0xB1, 0x6D, 0x61, 0x33, 0x8D, 0x9B,
|
||||
0xE7, 0xFD, 0x60, 0xA3, 0x83, 0xB5, 0xA3, 0x51, 0x55, 0x77, 0x90, 0xCF,
|
||||
0xDC, 0x22, 0x37, 0x8E, 0xD0, 0xE1, 0xAE, 0x09, 0xE3, 0x3D, 0x1E, 0xF8,
|
||||
0x80, 0xD1, 0x8B, 0xC2, 0xEC, 0x0A, 0xD7, 0x6B, 0x88, 0x8B, 0x8B, 0xA1,
|
||||
0x20, 0x22, 0xBE, 0x59, 0x5B, 0xE0, 0x23, 0x24, 0xA1, 0x49, 0x30, 0xBA,
|
||||
0xA9, 0x9E, 0xE8, 0xB1, 0x8A, 0x62, 0x16, 0xBF, 0x4E, 0xCA, 0x2E, 0x4E,
|
||||
0xBC, 0x29, 0xA8, 0x67, 0x13, 0xB7, 0x9F, 0x1D, 0x04, 0x44, 0xE5, 0x5F,
|
||||
0x35, 0x07, 0x11, 0xBC, 0xED, 0x19, 0x37, 0x21, 0xCF, 0x23, 0x48, 0x1F,
|
||||
0x72, 0x05, 0xDE, 0xE6, 0xE8, 0x7F, 0x33, 0x8A, 0x76, 0x4B, 0x2F, 0x95,
|
||||
0xDF, 0xF1, 0x5F, 0x84, 0x80, 0xD9, 0x46, 0xB4
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_SHA224[] = {
|
||||
0x62, 0xAA, 0x79, 0xA9, 0x18, 0x0E, 0x5F, 0x8C, 0xBB, 0xB7, 0x15, 0xF9,
|
||||
0x25, 0xBB, 0xFA, 0xD4, 0x3A, 0x34, 0xED, 0x9E, 0xA0, 0xA9, 0x18, 0x8D,
|
||||
0x5B, 0x55, 0x9A, 0x7E, 0x1E, 0x08, 0x08, 0x60, 0xC5, 0x1A, 0xC5, 0x89,
|
||||
0x08, 0xE2, 0x1B, 0xBD, 0x62, 0x50, 0x17, 0x76, 0x30, 0x2C, 0x9E, 0xCD,
|
||||
0xA4, 0x02, 0xAD, 0xB1, 0x6D, 0x44, 0x6D, 0xD5, 0xC6, 0x45, 0x41, 0xE5,
|
||||
0xEE, 0x1F, 0x8D, 0x7E, 0x08, 0x16, 0xA6, 0xE1, 0x5E, 0x0B, 0xA9, 0xCC,
|
||||
0xDB, 0x59, 0x55, 0x87, 0x09, 0x25, 0x70, 0x86, 0x84, 0x02, 0xC6, 0x3B,
|
||||
0x0B, 0x44, 0x4C, 0x46, 0x95, 0xF4, 0xF8, 0x5A, 0x91, 0x28, 0x3E, 0xB2,
|
||||
0x58, 0x2E, 0x06, 0x45, 0x49, 0xE0, 0x92, 0xE2, 0xC0, 0x66, 0xE6, 0x35,
|
||||
0xD9, 0x79, 0x7F, 0x17, 0x5E, 0x02, 0x73, 0x04, 0x77, 0x82, 0xE6, 0xDC,
|
||||
0x40, 0x21, 0x89, 0x8B, 0x37, 0x3E, 0x1E, 0x8D
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_SHA256[] = {
|
||||
0x0D, 0x55, 0xE2, 0xAA, 0x81, 0xDB, 0x8E, 0x82, 0x05, 0x17, 0xA5, 0x23,
|
||||
0xE7, 0x3B, 0x1D, 0xAF, 0xFB, 0x8C, 0xD0, 0x81, 0x20, 0x7B, 0xAA, 0x23,
|
||||
0x92, 0x87, 0x8C, 0xD1, 0x53, 0x85, 0x16, 0xDC, 0xBE, 0xAD, 0x6F, 0x35,
|
||||
0x98, 0x2D, 0x69, 0x84, 0xBF, 0xD9, 0x8A, 0x01, 0x17, 0x58, 0xB2, 0x6E,
|
||||
0x2C, 0x44, 0x9B, 0x90, 0xF1, 0xFB, 0x51, 0xE8, 0x6A, 0x90, 0x2D, 0x18,
|
||||
0x0E, 0xC0, 0x90, 0x10, 0x24, 0xA9, 0x1D, 0xB3, 0x58, 0x7A, 0x91, 0x30,
|
||||
0xBE, 0x22, 0xC7, 0xD3, 0xEC, 0xC3, 0x09, 0x5D, 0xBF, 0xE2, 0x80, 0x3A,
|
||||
0x7C, 0x85, 0xB4, 0xBC, 0xD1, 0xE9, 0xF0, 0x5C, 0xDE, 0x81, 0xA6, 0x38,
|
||||
0xB8, 0x42, 0xBB, 0x86, 0xC5, 0x9D, 0xCE, 0x7C, 0x2C, 0xEE, 0xD1, 0xDA,
|
||||
0x27, 0x48, 0x2B, 0xF5, 0xAB, 0xB9, 0xF7, 0x80, 0xD1, 0x90, 0x27, 0x90,
|
||||
0xBD, 0x44, 0x97, 0x60, 0xCD, 0x57, 0xC0, 0x7A
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_SHA384[] = {
|
||||
0x1D, 0xE3, 0x6A, 0xDD, 0x27, 0x4C, 0xC0, 0xA5, 0x27, 0xEF, 0xE6, 0x1F,
|
||||
0xD2, 0x91, 0x68, 0x59, 0x04, 0xAE, 0xBD, 0x99, 0x63, 0x56, 0x47, 0xC7,
|
||||
0x6F, 0x22, 0x16, 0x48, 0xD0, 0xF9, 0x18, 0xA9, 0xCA, 0xFA, 0x5D, 0x5C,
|
||||
0xA7, 0x65, 0x52, 0x8A, 0xC8, 0x44, 0x7E, 0x86, 0x5D, 0xA9, 0xA6, 0x55,
|
||||
0x65, 0x3E, 0xD9, 0x2D, 0x02, 0x38, 0xA8, 0x79, 0x28, 0x7F, 0xB6, 0xCF,
|
||||
0x82, 0xDD, 0x7E, 0x55, 0xE1, 0xB1, 0xBC, 0xE2, 0x19, 0x2B, 0x30, 0xC2,
|
||||
0x1B, 0x2B, 0xB0, 0x82, 0x46, 0xAC, 0x4B, 0xD1, 0xE2, 0x7D, 0xEB, 0x8C,
|
||||
0xFF, 0x95, 0xE9, 0x6A, 0x1C, 0x3D, 0x4D, 0xBF, 0x8F, 0x8B, 0x9C, 0xCD,
|
||||
0xEA, 0x85, 0xEE, 0x00, 0xDC, 0x1C, 0xA7, 0xEB, 0xD0, 0x8F, 0x99, 0xF1,
|
||||
0x16, 0x28, 0x24, 0x64, 0x04, 0x39, 0x2D, 0x58, 0x1E, 0x37, 0xDC, 0x04,
|
||||
0xBD, 0x31, 0xA2, 0x2F, 0xB3, 0x35, 0x56, 0xBF
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_SHA512[] = {
|
||||
0x69, 0x52, 0x1B, 0x51, 0x5E, 0x06, 0xCA, 0x9B, 0x16, 0x51, 0x5D, 0xCF,
|
||||
0x49, 0x25, 0x4A, 0xA1, 0x6A, 0x77, 0x4C, 0x36, 0x40, 0xF8, 0xB2, 0x9A,
|
||||
0x15, 0xEA, 0x5C, 0xE5, 0xE6, 0x82, 0xE0, 0x86, 0x82, 0x6B, 0x32, 0xF1,
|
||||
0x04, 0xC1, 0x5A, 0x1A, 0xED, 0x1E, 0x9A, 0xB6, 0x4C, 0x54, 0x9F, 0xD8,
|
||||
0x8D, 0xCC, 0xAC, 0x8A, 0xBB, 0x9C, 0x82, 0x3F, 0xA6, 0x53, 0x62, 0xB5,
|
||||
0x80, 0xE2, 0xBC, 0xDD, 0x67, 0x2B, 0xD9, 0x3F, 0xE4, 0x75, 0x92, 0x6B,
|
||||
0xAF, 0x62, 0x7C, 0x52, 0xF0, 0xEE, 0x33, 0xDF, 0x1B, 0x1D, 0x47, 0xE6,
|
||||
0x59, 0x56, 0xA5, 0xB9, 0x5C, 0xE6, 0x77, 0x78, 0x16, 0x63, 0x84, 0x05,
|
||||
0x6F, 0x0E, 0x2B, 0x31, 0x9D, 0xF7, 0x7F, 0xB2, 0x64, 0x71, 0xE0, 0x2D,
|
||||
0x3E, 0x62, 0xCE, 0xB5, 0x3F, 0x88, 0xDF, 0x2D, 0xAB, 0x98, 0x65, 0x91,
|
||||
0xDF, 0x70, 0x14, 0xA5, 0x3F, 0x36, 0xAB, 0x84
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_X931_SHA1[] = {
|
||||
0x86, 0xB4, 0x18, 0xBA, 0xD1, 0x80, 0xB6, 0x7C, 0x42, 0x45, 0x4D, 0xDF,
|
||||
0xE9, 0x2D, 0xE1, 0x83, 0x5F, 0xB5, 0x2F, 0xC9, 0xCD, 0xC4, 0xB2, 0x75,
|
||||
0x80, 0xA4, 0xF1, 0x4A, 0xE7, 0x83, 0x12, 0x1E, 0x1E, 0x14, 0xB8, 0xAC,
|
||||
0x35, 0xE2, 0xAA, 0x0B, 0x5C, 0xF8, 0x38, 0x4D, 0x04, 0xEE, 0xA9, 0x97,
|
||||
0x70, 0xFB, 0x5E, 0xE7, 0xB7, 0xE3, 0x62, 0x23, 0x4B, 0x38, 0xBE, 0xD6,
|
||||
0x53, 0x15, 0xF7, 0xDF, 0x87, 0xB4, 0x0E, 0xCC, 0xB1, 0x1A, 0x11, 0x19,
|
||||
0xEE, 0x51, 0xCC, 0x92, 0xDD, 0xBC, 0x63, 0x29, 0x63, 0x0C, 0x59, 0xD7,
|
||||
0x6F, 0x4C, 0x3C, 0x37, 0x5B, 0x37, 0x03, 0x61, 0x7D, 0x24, 0x1C, 0x99,
|
||||
0x48, 0xAF, 0x82, 0xFE, 0x32, 0x41, 0x9B, 0xB2, 0xDB, 0xEA, 0xED, 0x76,
|
||||
0x8E, 0x6E, 0xCA, 0x7E, 0x4E, 0x14, 0xBA, 0x30, 0x84, 0x1C, 0xB3, 0x67,
|
||||
0xA3, 0x29, 0x80, 0x70, 0x54, 0x68, 0x7D, 0x49
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_X931_SHA256[] = {
|
||||
0x7E, 0xA2, 0x77, 0xFE, 0xB8, 0x54, 0x8A, 0xC7, 0x7F, 0x64, 0x54, 0x89,
|
||||
0xE5, 0x52, 0x15, 0x8E, 0x52, 0x96, 0x4E, 0xA6, 0x58, 0x92, 0x1C, 0xDD,
|
||||
0xEA, 0xA2, 0x2D, 0x5C, 0xD1, 0x62, 0x00, 0x49, 0x05, 0x95, 0x73, 0xCF,
|
||||
0x16, 0x76, 0x68, 0xF6, 0xC6, 0x5E, 0x80, 0xB8, 0xB8, 0x7B, 0xC8, 0x9B,
|
||||
0xC6, 0x53, 0x88, 0x26, 0x20, 0x88, 0x73, 0xB6, 0x13, 0xB8, 0xF0, 0x4B,
|
||||
0x00, 0x85, 0xF3, 0xDD, 0x07, 0x50, 0xEB, 0x20, 0xC4, 0x38, 0x0E, 0x98,
|
||||
0xAD, 0x4E, 0x49, 0x2C, 0xD7, 0x65, 0xA5, 0x19, 0x0E, 0x59, 0x01, 0xEC,
|
||||
0x7E, 0x75, 0x89, 0x69, 0x2E, 0x63, 0x76, 0x85, 0x46, 0x8D, 0xA0, 0x8C,
|
||||
0x33, 0x1D, 0x82, 0x8C, 0x03, 0xEA, 0x69, 0x88, 0x35, 0xA1, 0x42, 0xBD,
|
||||
0x21, 0xED, 0x8D, 0xBC, 0xBC, 0xDB, 0x30, 0xFF, 0x86, 0xF0, 0x5B, 0xDC,
|
||||
0xE3, 0xE2, 0xE8, 0x0A, 0x0A, 0x29, 0x94, 0x80
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_X931_SHA384[] = {
|
||||
0x5C, 0x7D, 0x96, 0x35, 0xEC, 0x7E, 0x11, 0x38, 0xBB, 0x7B, 0xEC, 0x7B,
|
||||
0xF2, 0x82, 0x8E, 0x99, 0xBD, 0xEF, 0xD8, 0xAE, 0xD7, 0x39, 0x37, 0xCB,
|
||||
0xE6, 0x4F, 0x5E, 0x0A, 0x13, 0xE4, 0x2E, 0x40, 0xB9, 0xBE, 0x2E, 0xE3,
|
||||
0xEF, 0x78, 0x83, 0x18, 0x44, 0x35, 0x9C, 0x8E, 0xD7, 0x4A, 0x63, 0xF6,
|
||||
0x57, 0xC2, 0xB0, 0x08, 0x51, 0x73, 0xCF, 0xCA, 0x99, 0x66, 0xEE, 0x31,
|
||||
0xD8, 0x69, 0xE9, 0xAB, 0x13, 0x27, 0x7B, 0x41, 0x1E, 0x6D, 0x8D, 0xF1,
|
||||
0x3E, 0x9C, 0x35, 0x95, 0x58, 0xDD, 0x2B, 0xD5, 0xA0, 0x60, 0x41, 0x79,
|
||||
0x24, 0x22, 0xE4, 0xB7, 0xBF, 0x47, 0x53, 0xF6, 0x34, 0xD5, 0x7C, 0xFF,
|
||||
0x0E, 0x09, 0xEE, 0x2E, 0xE2, 0x37, 0xB9, 0xDE, 0xC5, 0x12, 0x44, 0x35,
|
||||
0xEF, 0x01, 0xE6, 0x5E, 0x39, 0x31, 0x2D, 0x71, 0xA5, 0xDC, 0xC6, 0x6D,
|
||||
0xE2, 0xCD, 0x85, 0xDB, 0x73, 0x82, 0x65, 0x28
|
||||
};
|
||||
|
||||
static const unsigned char kat_RSA_X931_SHA512[] = {
|
||||
0xA6, 0x65, 0xA2, 0x77, 0x4F, 0xB3, 0x86, 0xCB, 0x64, 0x3A, 0xC1, 0x63,
|
||||
0xFC, 0xA1, 0xAA, 0xCB, 0x9B, 0x79, 0xDD, 0x4B, 0xE1, 0xD9, 0xDA, 0xAC,
|
||||
0xE7, 0x47, 0x09, 0xB2, 0x11, 0x4B, 0x8A, 0xAA, 0x05, 0x9E, 0x77, 0xD7,
|
||||
0x3A, 0xBD, 0x5E, 0x53, 0x09, 0x4A, 0xE6, 0x0F, 0x5E, 0xF9, 0x14, 0x28,
|
||||
0xA0, 0x99, 0x74, 0x64, 0x70, 0x4E, 0xF2, 0xE3, 0xFA, 0xC7, 0xF8, 0xC5,
|
||||
0x6E, 0x2B, 0x79, 0x96, 0x0D, 0x0C, 0xC8, 0x10, 0x34, 0x53, 0xD2, 0xAF,
|
||||
0x17, 0x0E, 0xE0, 0xBF, 0x79, 0xF6, 0x04, 0x72, 0x10, 0xE0, 0xF6, 0xD0,
|
||||
0xCE, 0x8A, 0x6F, 0xA1, 0x95, 0x89, 0xBF, 0x58, 0x8F, 0x46, 0x5F, 0x09,
|
||||
0x9F, 0x09, 0xCA, 0x84, 0x15, 0x85, 0xE0, 0xED, 0x04, 0x2D, 0xFB, 0x7C,
|
||||
0x36, 0x35, 0x21, 0x31, 0xC3, 0xFD, 0x92, 0x42, 0x11, 0x30, 0x71, 0x1B,
|
||||
0x60, 0x83, 0x18, 0x88, 0xA3, 0xF5, 0x59, 0xC3
|
||||
};
|
||||
|
||||
int FIPS_selftest_rsa()
|
||||
{
|
||||
int ret = 0;
|
||||
RSA *key = NULL;
|
||||
EVP_PKEY pk;
|
||||
key = FIPS_rsa_new();
|
||||
setrsakey(key);
|
||||
pk.type = EVP_PKEY_RSA;
|
||||
pk.pkey.rsa = key;
|
||||
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_SHA1, sizeof(kat_RSA_SHA1),
|
||||
EVP_sha1(), EVP_MD_CTX_FLAG_PAD_PKCS1,
|
||||
"RSA SHA1 PKCS#1"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_SHA224, sizeof(kat_RSA_SHA224),
|
||||
EVP_sha224(), EVP_MD_CTX_FLAG_PAD_PKCS1,
|
||||
"RSA SHA224 PKCS#1"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_SHA256, sizeof(kat_RSA_SHA256),
|
||||
EVP_sha256(), EVP_MD_CTX_FLAG_PAD_PKCS1,
|
||||
"RSA SHA256 PKCS#1"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_SHA384, sizeof(kat_RSA_SHA384),
|
||||
EVP_sha384(), EVP_MD_CTX_FLAG_PAD_PKCS1,
|
||||
"RSA SHA384 PKCS#1"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_SHA512, sizeof(kat_RSA_SHA512),
|
||||
EVP_sha512(), EVP_MD_CTX_FLAG_PAD_PKCS1,
|
||||
"RSA SHA512 PKCS#1"))
|
||||
goto err;
|
||||
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_PSS_SHA1, sizeof(kat_RSA_PSS_SHA1),
|
||||
EVP_sha1(), EVP_MD_CTX_FLAG_PAD_PSS,
|
||||
"RSA SHA1 PSS"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_PSS_SHA224,
|
||||
sizeof(kat_RSA_PSS_SHA224), EVP_sha224(),
|
||||
EVP_MD_CTX_FLAG_PAD_PSS, "RSA SHA224 PSS"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_PSS_SHA256,
|
||||
sizeof(kat_RSA_PSS_SHA256), EVP_sha256(),
|
||||
EVP_MD_CTX_FLAG_PAD_PSS, "RSA SHA256 PSS"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_PSS_SHA384,
|
||||
sizeof(kat_RSA_PSS_SHA384), EVP_sha384(),
|
||||
EVP_MD_CTX_FLAG_PAD_PSS, "RSA SHA384 PSS"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_PSS_SHA512,
|
||||
sizeof(kat_RSA_PSS_SHA512), EVP_sha512(),
|
||||
EVP_MD_CTX_FLAG_PAD_PSS, "RSA SHA512 PSS"))
|
||||
goto err;
|
||||
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_X931_SHA1,
|
||||
sizeof(kat_RSA_X931_SHA1), EVP_sha1(),
|
||||
EVP_MD_CTX_FLAG_PAD_X931, "RSA SHA1 X931"))
|
||||
goto err;
|
||||
/* NB: SHA224 not supported in X9.31 */
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_X931_SHA256,
|
||||
sizeof(kat_RSA_X931_SHA256), EVP_sha256(),
|
||||
EVP_MD_CTX_FLAG_PAD_X931,
|
||||
"RSA SHA256 X931"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_X931_SHA384,
|
||||
sizeof(kat_RSA_X931_SHA384), EVP_sha384(),
|
||||
EVP_MD_CTX_FLAG_PAD_X931,
|
||||
"RSA SHA384 X931"))
|
||||
goto err;
|
||||
if (!fips_pkey_signature_test(&pk, kat_tbs, sizeof(kat_tbs) - 1,
|
||||
kat_RSA_X931_SHA512,
|
||||
sizeof(kat_RSA_X931_SHA512), EVP_sha512(),
|
||||
EVP_MD_CTX_FLAG_PAD_X931,
|
||||
"RSA SHA512 X931"))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
FIPS_rsa_free(key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* def OPENSSL_FIPS */
|
||||
@@ -0,0 +1,561 @@
|
||||
/* fips_rsa_sign.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2007.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
/*
|
||||
* FIPS versions of RSA_sign() and RSA_verify(). These will only have to deal
|
||||
* with SHA* signatures and by including pregenerated encodings all ASN1
|
||||
* dependencies can be avoided
|
||||
*/
|
||||
|
||||
/* Standard encodings including NULL parameter */
|
||||
|
||||
static const unsigned char sha1_bin[] = {
|
||||
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
|
||||
0x00, 0x04, 0x14
|
||||
};
|
||||
|
||||
static const unsigned char sha224_bin[] = {
|
||||
0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c
|
||||
};
|
||||
|
||||
static const unsigned char sha256_bin[] = {
|
||||
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
};
|
||||
|
||||
static const unsigned char sha384_bin[] = {
|
||||
0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
|
||||
};
|
||||
|
||||
static const unsigned char sha512_bin[] = {
|
||||
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
|
||||
};
|
||||
|
||||
/*
|
||||
* Alternate encodings with absent parameters. We don't generate signature
|
||||
* using this format but do tolerate received signatures of this form.
|
||||
*/
|
||||
|
||||
static unsigned char sha1_nn_bin[] = {
|
||||
0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04,
|
||||
0x14
|
||||
};
|
||||
|
||||
static unsigned char sha224_nn_bin[] = {
|
||||
0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x04, 0x04, 0x1c
|
||||
};
|
||||
|
||||
static unsigned char sha256_nn_bin[] = {
|
||||
0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x01, 0x04, 0x20
|
||||
};
|
||||
|
||||
static unsigned char sha384_nn_bin[] = {
|
||||
0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x02, 0x04, 0x30
|
||||
};
|
||||
|
||||
static unsigned char sha512_nn_bin[] = {
|
||||
0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
|
||||
0x04, 0x02, 0x03, 0x04, 0x40
|
||||
};
|
||||
|
||||
static const unsigned char *fips_digestinfo_encoding(int nid,
|
||||
unsigned int *len)
|
||||
{
|
||||
switch (nid) {
|
||||
|
||||
case NID_sha1:
|
||||
*len = sizeof(sha1_bin);
|
||||
return sha1_bin;
|
||||
|
||||
case NID_sha224:
|
||||
*len = sizeof(sha224_bin);
|
||||
return sha224_bin;
|
||||
|
||||
case NID_sha256:
|
||||
*len = sizeof(sha256_bin);
|
||||
return sha256_bin;
|
||||
|
||||
case NID_sha384:
|
||||
*len = sizeof(sha384_bin);
|
||||
return sha384_bin;
|
||||
|
||||
case NID_sha512:
|
||||
*len = sizeof(sha512_bin);
|
||||
return sha512_bin;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char *fips_digestinfo_nn_encoding(int nid,
|
||||
unsigned int *len)
|
||||
{
|
||||
switch (nid) {
|
||||
|
||||
case NID_sha1:
|
||||
*len = sizeof(sha1_nn_bin);
|
||||
return sha1_nn_bin;
|
||||
|
||||
case NID_sha224:
|
||||
*len = sizeof(sha224_nn_bin);
|
||||
return sha224_nn_bin;
|
||||
|
||||
case NID_sha256:
|
||||
*len = sizeof(sha256_nn_bin);
|
||||
return sha256_nn_bin;
|
||||
|
||||
case NID_sha384:
|
||||
*len = sizeof(sha384_nn_bin);
|
||||
return sha384_nn_bin;
|
||||
|
||||
case NID_sha512:
|
||||
*len = sizeof(sha512_nn_bin);
|
||||
return sha512_nn_bin;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int fips_rsa_sign(int type, const unsigned char *x, unsigned int y,
|
||||
unsigned char *sigret, unsigned int *siglen,
|
||||
EVP_MD_SVCTX * sv)
|
||||
{
|
||||
int i = 0, j, ret = 0;
|
||||
unsigned int dlen;
|
||||
const unsigned char *der;
|
||||
unsigned int m_len;
|
||||
int pad_mode = sv->mctx->flags & EVP_MD_CTX_FLAG_PAD_MASK;
|
||||
int rsa_pad_mode = 0;
|
||||
RSA *rsa = sv->key;
|
||||
/* Largest DigestInfo: 19 (max encoding) + max MD */
|
||||
unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE];
|
||||
unsigned char md[EVP_MAX_MD_SIZE + 1];
|
||||
|
||||
EVP_DigestFinal_ex(sv->mctx, md, &m_len);
|
||||
|
||||
if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) {
|
||||
ret = rsa->meth->rsa_sign(type, md, m_len, sigret, siglen, rsa);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931) {
|
||||
int hash_id;
|
||||
memcpy(tmpdinfo, md, m_len);
|
||||
hash_id = RSA_X931_hash_id(M_EVP_MD_CTX_type(sv->mctx));
|
||||
if (hash_id == -1) {
|
||||
RSAerr(RSA_F_FIPS_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
return 0;
|
||||
}
|
||||
tmpdinfo[m_len] = (unsigned char)hash_id;
|
||||
i = m_len + 1;
|
||||
rsa_pad_mode = RSA_X931_PADDING;
|
||||
} else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PKCS1) {
|
||||
|
||||
der = fips_digestinfo_encoding(type, &dlen);
|
||||
|
||||
if (!der) {
|
||||
RSAerr(RSA_F_FIPS_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(tmpdinfo, der, dlen);
|
||||
memcpy(tmpdinfo + dlen, md, m_len);
|
||||
|
||||
i = dlen + m_len;
|
||||
rsa_pad_mode = RSA_PKCS1_PADDING;
|
||||
|
||||
} else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PSS) {
|
||||
unsigned char *sbuf;
|
||||
int saltlen;
|
||||
i = RSA_size(rsa);
|
||||
sbuf = OPENSSL_malloc(RSA_size(rsa));
|
||||
saltlen = M_EVP_MD_CTX_FLAG_PSS_SALT(sv->mctx);
|
||||
if (saltlen == EVP_MD_CTX_FLAG_PSS_MDLEN)
|
||||
saltlen = -1;
|
||||
else if (saltlen == EVP_MD_CTX_FLAG_PSS_MREC)
|
||||
saltlen = -2;
|
||||
if (!sbuf) {
|
||||
RSAerr(RSA_F_FIPS_RSA_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
goto psserr;
|
||||
}
|
||||
if (!RSA_padding_add_PKCS1_PSS(rsa, sbuf, md,
|
||||
M_EVP_MD_CTX_md(sv->mctx), saltlen))
|
||||
goto psserr;
|
||||
j = rsa->meth->rsa_priv_enc(i, sbuf, sigret, rsa, RSA_NO_PADDING);
|
||||
if (j > 0) {
|
||||
ret = 1;
|
||||
*siglen = j;
|
||||
}
|
||||
psserr:
|
||||
OPENSSL_cleanse(md, m_len);
|
||||
OPENSSL_cleanse(sbuf, i);
|
||||
OPENSSL_free(sbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
j = RSA_size(rsa);
|
||||
if (i > (j - RSA_PKCS1_PADDING_SIZE)) {
|
||||
RSAerr(RSA_F_FIPS_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
|
||||
goto done;
|
||||
}
|
||||
/* NB: call underlying method directly to avoid FIPS blocking */
|
||||
j = rsa->meth->rsa_priv_enc(i, tmpdinfo, sigret, rsa, rsa_pad_mode);
|
||||
if (j > 0) {
|
||||
ret = 1;
|
||||
*siglen = j;
|
||||
}
|
||||
|
||||
done:
|
||||
OPENSSL_cleanse(tmpdinfo, i);
|
||||
OPENSSL_cleanse(md, m_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fips_rsa_verify(int dtype,
|
||||
const unsigned char *x, unsigned int y,
|
||||
unsigned char *sigbuf, unsigned int siglen,
|
||||
EVP_MD_SVCTX * sv)
|
||||
{
|
||||
int i, ret = 0;
|
||||
unsigned int dlen, diglen;
|
||||
int pad_mode = sv->mctx->flags & EVP_MD_CTX_FLAG_PAD_MASK;
|
||||
int rsa_pad_mode = 0;
|
||||
unsigned char *s;
|
||||
const unsigned char *der;
|
||||
unsigned char dig[EVP_MAX_MD_SIZE];
|
||||
RSA *rsa = sv->key;
|
||||
|
||||
if (siglen != (unsigned int)RSA_size(sv->key)) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH);
|
||||
return (0);
|
||||
}
|
||||
|
||||
EVP_DigestFinal_ex(sv->mctx, dig, &diglen);
|
||||
|
||||
if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) {
|
||||
return rsa->meth->rsa_verify(dtype, dig, diglen, sigbuf, siglen, rsa);
|
||||
}
|
||||
|
||||
s = OPENSSL_malloc((unsigned int)siglen);
|
||||
if (s == NULL) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931)
|
||||
rsa_pad_mode = RSA_X931_PADDING;
|
||||
else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PKCS1)
|
||||
rsa_pad_mode = RSA_PKCS1_PADDING;
|
||||
else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PSS)
|
||||
rsa_pad_mode = RSA_NO_PADDING;
|
||||
|
||||
/* NB: call underlying method directly to avoid FIPS blocking */
|
||||
i = rsa->meth->rsa_pub_dec((int)siglen, sigbuf, s, rsa, rsa_pad_mode);
|
||||
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
|
||||
if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931) {
|
||||
int hash_id;
|
||||
if (i != (int)(diglen + 1)) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
hash_id = RSA_X931_hash_id(M_EVP_MD_CTX_type(sv->mctx));
|
||||
if (hash_id == -1) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (s[diglen] != (unsigned char)hash_id) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
if (memcmp(s, dig, diglen)) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
} else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PKCS1) {
|
||||
|
||||
der = fips_digestinfo_encoding(dtype, &dlen);
|
||||
|
||||
if (!der) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare, DigestInfo length, DigestInfo header and finally digest
|
||||
* value itself
|
||||
*/
|
||||
|
||||
/* If length mismatch try alternate encoding */
|
||||
if (i != (int)(dlen + diglen))
|
||||
der = fips_digestinfo_nn_encoding(dtype, &dlen);
|
||||
|
||||
if ((i != (int)(dlen + diglen)) || memcmp(der, s, dlen)
|
||||
|| memcmp(s + dlen, dig, diglen)) {
|
||||
RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
} else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PSS) {
|
||||
int saltlen;
|
||||
saltlen = M_EVP_MD_CTX_FLAG_PSS_SALT(sv->mctx);
|
||||
if (saltlen == EVP_MD_CTX_FLAG_PSS_MDLEN)
|
||||
saltlen = -1;
|
||||
else if (saltlen == EVP_MD_CTX_FLAG_PSS_MREC)
|
||||
saltlen = -2;
|
||||
ret = RSA_verify_PKCS1_PSS(rsa, dig, M_EVP_MD_CTX_md(sv->mctx),
|
||||
s, saltlen);
|
||||
if (ret < 0)
|
||||
ret = 0;
|
||||
}
|
||||
err:
|
||||
if (s != NULL) {
|
||||
OPENSSL_cleanse(s, siglen);
|
||||
OPENSSL_free(s);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
# define EVP_PKEY_RSA_fips_method \
|
||||
(evp_sign_method *)fips_rsa_sign, \
|
||||
(evp_verify_method *)fips_rsa_verify, \
|
||||
{EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
|
||||
|
||||
static int init(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return SHA1_Init(ctx->md_data);
|
||||
}
|
||||
|
||||
static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
return SHA1_Update(ctx->md_data, data, count);
|
||||
}
|
||||
|
||||
static int final(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
return SHA1_Final(md, ctx->md_data);
|
||||
}
|
||||
|
||||
static const EVP_MD sha1_md = {
|
||||
NID_sha1,
|
||||
NID_sha1WithRSAEncryption,
|
||||
SHA_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX,
|
||||
init,
|
||||
update,
|
||||
final,
|
||||
NULL,
|
||||
NULL,
|
||||
EVP_PKEY_RSA_fips_method,
|
||||
SHA_CBLOCK,
|
||||
sizeof(EVP_MD *) + sizeof(SHA_CTX),
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_sha1(void)
|
||||
{
|
||||
return (&sha1_md);
|
||||
}
|
||||
|
||||
static int init224(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return SHA224_Init(ctx->md_data);
|
||||
}
|
||||
|
||||
static int init256(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return SHA256_Init(ctx->md_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even though there're separate SHA224_[Update|Final], we call
|
||||
* SHA256 functions even in SHA224 context. This is what happens
|
||||
* there anyway, so we can spare few CPU cycles:-)
|
||||
*/
|
||||
static int update256(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
return SHA256_Update(ctx->md_data, data, count);
|
||||
}
|
||||
|
||||
static int final256(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
return SHA256_Final(md, ctx->md_data);
|
||||
}
|
||||
|
||||
static const EVP_MD sha224_md = {
|
||||
NID_sha224,
|
||||
NID_sha224WithRSAEncryption,
|
||||
SHA224_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX,
|
||||
init224,
|
||||
update256,
|
||||
final256,
|
||||
NULL,
|
||||
NULL,
|
||||
EVP_PKEY_RSA_fips_method,
|
||||
SHA256_CBLOCK,
|
||||
sizeof(EVP_MD *) + sizeof(SHA256_CTX),
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_sha224(void)
|
||||
{
|
||||
return (&sha224_md);
|
||||
}
|
||||
|
||||
static const EVP_MD sha256_md = {
|
||||
NID_sha256,
|
||||
NID_sha256WithRSAEncryption,
|
||||
SHA256_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX,
|
||||
init256,
|
||||
update256,
|
||||
final256,
|
||||
NULL,
|
||||
NULL,
|
||||
EVP_PKEY_RSA_fips_method,
|
||||
SHA256_CBLOCK,
|
||||
sizeof(EVP_MD *) + sizeof(SHA256_CTX),
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_sha256(void)
|
||||
{
|
||||
return (&sha256_md);
|
||||
}
|
||||
|
||||
static int init384(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return SHA384_Init(ctx->md_data);
|
||||
}
|
||||
|
||||
static int init512(EVP_MD_CTX *ctx)
|
||||
{
|
||||
return SHA512_Init(ctx->md_data);
|
||||
}
|
||||
|
||||
/* See comment in SHA224/256 section */
|
||||
static int update512(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
return SHA512_Update(ctx->md_data, data, count);
|
||||
}
|
||||
|
||||
static int final512(EVP_MD_CTX *ctx, unsigned char *md)
|
||||
{
|
||||
return SHA512_Final(md, ctx->md_data);
|
||||
}
|
||||
|
||||
static const EVP_MD sha384_md = {
|
||||
NID_sha384,
|
||||
NID_sha384WithRSAEncryption,
|
||||
SHA384_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX,
|
||||
init384,
|
||||
update512,
|
||||
final512,
|
||||
NULL,
|
||||
NULL,
|
||||
EVP_PKEY_RSA_fips_method,
|
||||
SHA512_CBLOCK,
|
||||
sizeof(EVP_MD *) + sizeof(SHA512_CTX),
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_sha384(void)
|
||||
{
|
||||
return (&sha384_md);
|
||||
}
|
||||
|
||||
static const EVP_MD sha512_md = {
|
||||
NID_sha512,
|
||||
NID_sha512WithRSAEncryption,
|
||||
SHA512_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_FIPS | EVP_MD_FLAG_SVCTX,
|
||||
init512,
|
||||
update512,
|
||||
final512,
|
||||
NULL,
|
||||
NULL,
|
||||
EVP_PKEY_RSA_fips_method,
|
||||
SHA512_CBLOCK,
|
||||
sizeof(EVP_MD *) + sizeof(SHA512_CTX),
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_sha512(void)
|
||||
{
|
||||
return (&sha512_md);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,273 @@
|
||||
/* crypto/rsa/rsa_gen.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/fips.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
|
||||
extern int fips_check_rsa(RSA *rsa);
|
||||
|
||||
/* X9.31 RSA key derivation and generation */
|
||||
|
||||
int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
|
||||
BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2,
|
||||
const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2,
|
||||
const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL;
|
||||
BN_CTX *ctx = NULL, *ctx2 = NULL;
|
||||
|
||||
if (!rsa)
|
||||
goto err;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
BN_CTX_start(ctx);
|
||||
if (!ctx)
|
||||
goto err;
|
||||
|
||||
r0 = BN_CTX_get(ctx);
|
||||
r1 = BN_CTX_get(ctx);
|
||||
r2 = BN_CTX_get(ctx);
|
||||
r3 = BN_CTX_get(ctx);
|
||||
|
||||
if (r3 == NULL)
|
||||
goto err;
|
||||
if (!rsa->e) {
|
||||
rsa->e = BN_dup(e);
|
||||
if (!rsa->e)
|
||||
goto err;
|
||||
} else
|
||||
e = rsa->e;
|
||||
|
||||
/*
|
||||
* If not all parameters present only calculate what we can. This allows
|
||||
* test programs to output selective parameters.
|
||||
*/
|
||||
|
||||
if (Xp && !rsa->p) {
|
||||
rsa->p = BN_new();
|
||||
if (!rsa->p)
|
||||
goto err;
|
||||
|
||||
if (!BN_X931_derive_prime_ex(rsa->p, p1, p2,
|
||||
Xp, Xp1, Xp2, e, ctx, cb))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (Xq && !rsa->q) {
|
||||
rsa->q = BN_new();
|
||||
if (!rsa->q)
|
||||
goto err;
|
||||
if (!BN_X931_derive_prime_ex(rsa->q, q1, q2,
|
||||
Xq, Xq1, Xq2, e, ctx, cb))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!rsa->p || !rsa->q) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since both primes are set we can now calculate all remaining
|
||||
* components.
|
||||
*/
|
||||
|
||||
/* calculate n */
|
||||
rsa->n = BN_new();
|
||||
if (rsa->n == NULL)
|
||||
goto err;
|
||||
if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d */
|
||||
if (!BN_sub(r1, rsa->p, BN_value_one()))
|
||||
goto err; /* p-1 */
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one()))
|
||||
goto err; /* q-1 */
|
||||
if (!BN_mul(r0, r1, r2, ctx))
|
||||
goto err; /* (p-1)(q-1) */
|
||||
|
||||
if (!BN_gcd(r3, r1, r2, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_div(r0, NULL, r0, r3, ctx))
|
||||
goto err; /* LCM((p-1)(q-1)) */
|
||||
|
||||
ctx2 = BN_CTX_new();
|
||||
if (!ctx2)
|
||||
goto err;
|
||||
|
||||
rsa->d = BN_mod_inverse(NULL, rsa->e, r0, ctx2); /* d */
|
||||
if (rsa->d == NULL)
|
||||
goto err;
|
||||
|
||||
/* calculate d mod (p-1) */
|
||||
rsa->dmp1 = BN_new();
|
||||
if (rsa->dmp1 == NULL)
|
||||
goto err;
|
||||
if (!BN_mod(rsa->dmp1, rsa->d, r1, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d mod (q-1) */
|
||||
rsa->dmq1 = BN_new();
|
||||
if (rsa->dmq1 == NULL)
|
||||
goto err;
|
||||
if (!BN_mod(rsa->dmq1, rsa->d, r2, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate inverse of q mod p */
|
||||
rsa->iqmp = BN_mod_inverse(NULL, rsa->q, rsa->p, ctx2);
|
||||
|
||||
err:
|
||||
if (ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (ctx2)
|
||||
BN_CTX_free(ctx2);
|
||||
/* If this is set all calls successful */
|
||||
if (rsa->iqmp != NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
int ok = 0;
|
||||
BIGNUM *Xp = NULL, *Xq = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (bits < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS) {
|
||||
FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY_EX, FIPS_R_KEY_TOO_SHORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bits & 0xff) {
|
||||
FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY_EX, FIPS_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FIPS_selftest_failed()) {
|
||||
FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY_EX, FIPS_R_FIPS_SELFTEST_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (!ctx)
|
||||
goto error;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
Xp = BN_CTX_get(ctx);
|
||||
Xq = BN_CTX_get(ctx);
|
||||
if (!BN_X931_generate_Xpq(Xp, Xq, bits, ctx))
|
||||
goto error;
|
||||
|
||||
rsa->p = BN_new();
|
||||
rsa->q = BN_new();
|
||||
if (!rsa->p || !rsa->q)
|
||||
goto error;
|
||||
|
||||
/* Generate two primes from Xp, Xq */
|
||||
|
||||
if (!BN_X931_generate_prime_ex(rsa->p, NULL, NULL, NULL, NULL, Xp,
|
||||
e, ctx, cb))
|
||||
goto error;
|
||||
|
||||
if (!BN_X931_generate_prime_ex(rsa->q, NULL, NULL, NULL, NULL, Xq,
|
||||
e, ctx, cb))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Since rsa->p and rsa->q are valid this call will just derive remaining
|
||||
* RSA components.
|
||||
*/
|
||||
|
||||
if (!RSA_X931_derive_ex(rsa, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, e, cb))
|
||||
goto error;
|
||||
|
||||
if (!fips_check_rsa(rsa))
|
||||
goto error;
|
||||
|
||||
ok = 1;
|
||||
|
||||
error:
|
||||
if (ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
|
||||
if (ok)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,368 @@
|
||||
/* fips_rsagtest.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005,2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
#ifndef OPENSSL_FIPS
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("No FIPS RSA support\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# include <openssl/rsa.h>
|
||||
# include "fips_utl.h"
|
||||
|
||||
int rsa_test(FILE *out, FILE *in);
|
||||
static int rsa_printkey1(FILE *out, RSA *rsa,
|
||||
BIGNUM *Xp1, BIGNUM *Xp2, BIGNUM *Xp, BIGNUM *e);
|
||||
static int rsa_printkey2(FILE *out, RSA *rsa,
|
||||
BIGNUM *Xq1, BIGNUM *Xq2, BIGNUM *Xq);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *in = NULL, *out = NULL;
|
||||
|
||||
int ret = 1;
|
||||
|
||||
if (!FIPS_mode_set(1)) {
|
||||
do_print_errors();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
in = stdin;
|
||||
else
|
||||
in = fopen(argv[1], "r");
|
||||
|
||||
if (argc < 2)
|
||||
out = stdout;
|
||||
else
|
||||
out = fopen(argv[2], "w");
|
||||
|
||||
if (!in) {
|
||||
fprintf(stderr, "FATAL input initialization error\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!out) {
|
||||
fprintf(stderr, "FATAL output initialization error\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!rsa_test(out, in)) {
|
||||
fprintf(stderr, "FATAL RSAGTEST file processing error\n");
|
||||
goto end;
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
|
||||
if (ret)
|
||||
do_print_errors();
|
||||
|
||||
if (in && (in != stdin))
|
||||
fclose(in);
|
||||
if (out && (out != stdout))
|
||||
fclose(out);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
# define RSA_TEST_MAXLINELEN 10240
|
||||
|
||||
int rsa_test(FILE *out, FILE *in)
|
||||
{
|
||||
char *linebuf, *olinebuf, *p, *q;
|
||||
char *keyword, *value;
|
||||
RSA *rsa = NULL;
|
||||
BIGNUM *Xp1 = NULL, *Xp2 = NULL, *Xp = NULL;
|
||||
BIGNUM *Xq1 = NULL, *Xq2 = NULL, *Xq = NULL;
|
||||
BIGNUM *e = NULL;
|
||||
int ret = 0;
|
||||
int lnum = 0;
|
||||
|
||||
olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
|
||||
linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
|
||||
|
||||
if (!linebuf || !olinebuf)
|
||||
goto error;
|
||||
|
||||
while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) {
|
||||
lnum++;
|
||||
strcpy(linebuf, olinebuf);
|
||||
keyword = linebuf;
|
||||
/* Skip leading space */
|
||||
while (isspace((unsigned char)*keyword))
|
||||
keyword++;
|
||||
|
||||
/* Look for = sign */
|
||||
p = strchr(linebuf, '=');
|
||||
|
||||
/*
|
||||
* If no = or starts with [ (for [foo = bar] line) just copy
|
||||
*/
|
||||
if (!p || *keyword == '[') {
|
||||
if (fputs(olinebuf, out) < 0)
|
||||
goto error;
|
||||
continue;
|
||||
}
|
||||
|
||||
q = p - 1;
|
||||
|
||||
/* Remove trailing space */
|
||||
while (isspace((unsigned char)*q))
|
||||
*q-- = 0;
|
||||
|
||||
*p = 0;
|
||||
value = p + 1;
|
||||
|
||||
/* Remove leading space from value */
|
||||
while (isspace((unsigned char)*value))
|
||||
value++;
|
||||
|
||||
/* Remove trailing space from value */
|
||||
p = value + strlen(value) - 1;
|
||||
|
||||
while (*p == '\n' || isspace((unsigned char)*p))
|
||||
*p-- = 0;
|
||||
|
||||
if (!strcmp(keyword, "xp1")) {
|
||||
if (Xp1 || !do_hex2bn(&Xp1, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "xp2")) {
|
||||
if (Xp2 || !do_hex2bn(&Xp2, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "Xp")) {
|
||||
if (Xp || !do_hex2bn(&Xp, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "xq1")) {
|
||||
if (Xq1 || !do_hex2bn(&Xq1, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "xq2")) {
|
||||
if (Xq2 || !do_hex2bn(&Xq2, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "Xq")) {
|
||||
if (Xq || !do_hex2bn(&Xq, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "e")) {
|
||||
if (e || !do_hex2bn(&e, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "p1"))
|
||||
continue;
|
||||
else if (!strcmp(keyword, "p2"))
|
||||
continue;
|
||||
else if (!strcmp(keyword, "p"))
|
||||
continue;
|
||||
else if (!strcmp(keyword, "q1"))
|
||||
continue;
|
||||
else if (!strcmp(keyword, "q2"))
|
||||
continue;
|
||||
else if (!strcmp(keyword, "q"))
|
||||
continue;
|
||||
else if (!strcmp(keyword, "n"))
|
||||
continue;
|
||||
else if (!strcmp(keyword, "d"))
|
||||
continue;
|
||||
else
|
||||
goto parse_error;
|
||||
|
||||
fputs(olinebuf, out);
|
||||
|
||||
if (e && Xp1 && Xp2 && Xp) {
|
||||
rsa = FIPS_rsa_new();
|
||||
if (!rsa)
|
||||
goto error;
|
||||
if (!rsa_printkey1(out, rsa, Xp1, Xp2, Xp, e))
|
||||
goto error;
|
||||
BN_free(Xp1);
|
||||
Xp1 = NULL;
|
||||
BN_free(Xp2);
|
||||
Xp2 = NULL;
|
||||
BN_free(Xp);
|
||||
Xp = NULL;
|
||||
BN_free(e);
|
||||
e = NULL;
|
||||
}
|
||||
|
||||
if (rsa && Xq1 && Xq2 && Xq) {
|
||||
if (!rsa_printkey2(out, rsa, Xq1, Xq2, Xq))
|
||||
goto error;
|
||||
BN_free(Xq1);
|
||||
Xq1 = NULL;
|
||||
BN_free(Xq2);
|
||||
Xq2 = NULL;
|
||||
BN_free(Xq);
|
||||
Xq = NULL;
|
||||
FIPS_rsa_free(rsa);
|
||||
rsa = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
|
||||
if (olinebuf)
|
||||
OPENSSL_free(olinebuf);
|
||||
if (linebuf)
|
||||
OPENSSL_free(linebuf);
|
||||
|
||||
if (Xp1)
|
||||
BN_free(Xp1);
|
||||
if (Xp2)
|
||||
BN_free(Xp2);
|
||||
if (Xp)
|
||||
BN_free(Xp);
|
||||
if (Xq1)
|
||||
BN_free(Xq1);
|
||||
if (Xq1)
|
||||
BN_free(Xq1);
|
||||
if (Xq2)
|
||||
BN_free(Xq2);
|
||||
if (Xq)
|
||||
BN_free(Xq);
|
||||
if (e)
|
||||
BN_free(e);
|
||||
if (rsa)
|
||||
FIPS_rsa_free(rsa);
|
||||
|
||||
return ret;
|
||||
|
||||
parse_error:
|
||||
|
||||
fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
|
||||
|
||||
goto error;
|
||||
|
||||
}
|
||||
|
||||
static int rsa_printkey1(FILE *out, RSA *rsa,
|
||||
BIGNUM *Xp1, BIGNUM *Xp2, BIGNUM *Xp, BIGNUM *e)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *p1 = NULL, *p2 = NULL;
|
||||
p1 = BN_new();
|
||||
p2 = BN_new();
|
||||
if (!p1 || !p2)
|
||||
goto error;
|
||||
|
||||
if (!RSA_X931_derive_ex(rsa, p1, p2, NULL, NULL, Xp1, Xp2, Xp,
|
||||
NULL, NULL, NULL, e, NULL))
|
||||
goto error;
|
||||
|
||||
do_bn_print_name(out, "p1", p1);
|
||||
do_bn_print_name(out, "p2", p2);
|
||||
do_bn_print_name(out, "p", rsa->p);
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
if (p1)
|
||||
BN_free(p1);
|
||||
if (p2)
|
||||
BN_free(p2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rsa_printkey2(FILE *out, RSA *rsa,
|
||||
BIGNUM *Xq1, BIGNUM *Xq2, BIGNUM *Xq)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *q1 = NULL, *q2 = NULL;
|
||||
q1 = BN_new();
|
||||
q2 = BN_new();
|
||||
if (!q1 || !q2)
|
||||
goto error;
|
||||
|
||||
if (!RSA_X931_derive_ex(rsa, NULL, NULL, q1, q2, NULL, NULL, NULL,
|
||||
Xq1, Xq2, Xq, NULL, NULL))
|
||||
goto error;
|
||||
|
||||
do_bn_print_name(out, "q1", q1);
|
||||
do_bn_print_name(out, "q2", q2);
|
||||
do_bn_print_name(out, "q", rsa->q);
|
||||
do_bn_print_name(out, "n", rsa->n);
|
||||
do_bn_print_name(out, "d", rsa->d);
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
if (q1)
|
||||
BN_free(q1);
|
||||
if (q2)
|
||||
BN_free(q2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,349 @@
|
||||
/* fips_rsastest.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
#ifndef OPENSSL_FIPS
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("No FIPS RSA support\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# include <openssl/rsa.h>
|
||||
# include "fips_utl.h"
|
||||
|
||||
static int rsa_stest(FILE *out, FILE *in, int Saltlen);
|
||||
static int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst,
|
||||
unsigned char *Msg, long Msglen, int Saltlen);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *in = NULL, *out = NULL;
|
||||
|
||||
int ret = 1, Saltlen = -1;
|
||||
|
||||
if (!FIPS_mode_set(1)) {
|
||||
do_print_errors();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((argc > 2) && !strcmp("-saltlen", argv[1])) {
|
||||
Saltlen = atoi(argv[2]);
|
||||
if (Saltlen < 0) {
|
||||
fprintf(stderr, "FATAL: Invalid salt length\n");
|
||||
goto end;
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
} else if ((argc > 1) && !strcmp("-x931", argv[1])) {
|
||||
Saltlen = -2;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
in = stdin;
|
||||
else
|
||||
in = fopen(argv[1], "r");
|
||||
|
||||
if (argc < 2)
|
||||
out = stdout;
|
||||
else
|
||||
out = fopen(argv[2], "w");
|
||||
|
||||
if (!in) {
|
||||
fprintf(stderr, "FATAL input initialization error\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!out) {
|
||||
fprintf(stderr, "FATAL output initialization error\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!rsa_stest(out, in, Saltlen)) {
|
||||
fprintf(stderr, "FATAL RSASTEST file processing error\n");
|
||||
goto end;
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
|
||||
if (ret)
|
||||
do_print_errors();
|
||||
|
||||
if (in && (in != stdin))
|
||||
fclose(in);
|
||||
if (out && (out != stdout))
|
||||
fclose(out);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
# define RSA_TEST_MAXLINELEN 10240
|
||||
|
||||
int rsa_stest(FILE *out, FILE *in, int Saltlen)
|
||||
{
|
||||
char *linebuf, *olinebuf, *p, *q;
|
||||
char *keyword, *value;
|
||||
RSA *rsa = NULL;
|
||||
const EVP_MD *dgst = NULL;
|
||||
unsigned char *Msg = NULL;
|
||||
long Msglen = -1;
|
||||
int keylen = -1, current_keylen = -1;
|
||||
int ret = 0;
|
||||
int lnum = 0;
|
||||
|
||||
olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
|
||||
linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
|
||||
|
||||
if (!linebuf || !olinebuf)
|
||||
goto error;
|
||||
|
||||
while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) {
|
||||
lnum++;
|
||||
strcpy(linebuf, olinebuf);
|
||||
keyword = linebuf;
|
||||
/* Skip leading space */
|
||||
while (isspace((unsigned char)*keyword))
|
||||
keyword++;
|
||||
|
||||
/* Look for = sign */
|
||||
p = strchr(linebuf, '=');
|
||||
|
||||
/* If no = just copy */
|
||||
if (!p) {
|
||||
if (fputs(olinebuf, out) < 0)
|
||||
goto error;
|
||||
continue;
|
||||
}
|
||||
|
||||
q = p - 1;
|
||||
|
||||
/* Remove trailing space */
|
||||
while (isspace((unsigned char)*q))
|
||||
*q-- = 0;
|
||||
|
||||
*p = 0;
|
||||
value = p + 1;
|
||||
|
||||
/* Remove leading space from value */
|
||||
while (isspace((unsigned char)*value))
|
||||
value++;
|
||||
|
||||
/* Remove trailing space from value */
|
||||
p = value + strlen(value) - 1;
|
||||
|
||||
while (*p == '\n' || isspace((unsigned char)*p))
|
||||
*p-- = 0;
|
||||
|
||||
/* Look for [mod = XXX] for key length */
|
||||
|
||||
if (!strcmp(keyword, "[mod")) {
|
||||
p = value + strlen(value) - 1;
|
||||
if (*p != ']')
|
||||
goto parse_error;
|
||||
*p = 0;
|
||||
keylen = atoi(value);
|
||||
if (keylen < 0)
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "SHAAlg")) {
|
||||
if (!strcmp(value, "SHA1"))
|
||||
dgst = EVP_sha1();
|
||||
else if (!strcmp(value, "SHA224"))
|
||||
dgst = EVP_sha224();
|
||||
else if (!strcmp(value, "SHA256"))
|
||||
dgst = EVP_sha256();
|
||||
else if (!strcmp(value, "SHA384"))
|
||||
dgst = EVP_sha384();
|
||||
else if (!strcmp(value, "SHA512"))
|
||||
dgst = EVP_sha512();
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"FATAL: unsupported algorithm \"%s\"\n", value);
|
||||
goto parse_error;
|
||||
}
|
||||
} else if (!strcmp(keyword, "Msg")) {
|
||||
if (Msg)
|
||||
goto parse_error;
|
||||
if (strlen(value) & 1)
|
||||
*(--value) = '0';
|
||||
Msg = hex2bin_m(value, &Msglen);
|
||||
if (!Msg)
|
||||
goto parse_error;
|
||||
}
|
||||
|
||||
fputs(olinebuf, out);
|
||||
|
||||
/*
|
||||
* If key length has changed, generate and output public key
|
||||
* components of new RSA private key.
|
||||
*/
|
||||
|
||||
if (keylen != current_keylen) {
|
||||
BIGNUM *bn_e;
|
||||
if (rsa)
|
||||
FIPS_rsa_free(rsa);
|
||||
rsa = FIPS_rsa_new();
|
||||
if (!rsa)
|
||||
goto error;
|
||||
bn_e = BN_new();
|
||||
if (!bn_e || !BN_set_word(bn_e, 0x1001))
|
||||
goto error;
|
||||
if (!RSA_X931_generate_key_ex(rsa, keylen, bn_e, NULL))
|
||||
goto error;
|
||||
BN_free(bn_e);
|
||||
fputs("n = ", out);
|
||||
do_bn_print(out, rsa->n);
|
||||
fputs("\ne = ", out);
|
||||
do_bn_print(out, rsa->e);
|
||||
fputs("\n", out);
|
||||
current_keylen = keylen;
|
||||
}
|
||||
|
||||
if (Msg && dgst) {
|
||||
if (!rsa_printsig(out, rsa, dgst, Msg, Msglen, Saltlen))
|
||||
goto error;
|
||||
OPENSSL_free(Msg);
|
||||
Msg = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
|
||||
if (olinebuf)
|
||||
OPENSSL_free(olinebuf);
|
||||
if (linebuf)
|
||||
OPENSSL_free(linebuf);
|
||||
if (rsa)
|
||||
FIPS_rsa_free(rsa);
|
||||
|
||||
return ret;
|
||||
|
||||
parse_error:
|
||||
|
||||
fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
|
||||
|
||||
goto error;
|
||||
|
||||
}
|
||||
|
||||
static int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst,
|
||||
unsigned char *Msg, long Msglen, int Saltlen)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char *sigbuf = NULL;
|
||||
int i, siglen;
|
||||
/* EVP_PKEY structure */
|
||||
EVP_PKEY pk;
|
||||
EVP_MD_CTX ctx;
|
||||
pk.type = EVP_PKEY_RSA;
|
||||
pk.pkey.rsa = rsa;
|
||||
|
||||
siglen = RSA_size(rsa);
|
||||
sigbuf = OPENSSL_malloc(siglen);
|
||||
if (!sigbuf)
|
||||
goto error;
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
if (Saltlen >= 0) {
|
||||
M_EVP_MD_CTX_set_flags(&ctx,
|
||||
EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16));
|
||||
} else if (Saltlen == -2)
|
||||
M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931);
|
||||
if (!EVP_SignInit_ex(&ctx, dgst, NULL))
|
||||
goto error;
|
||||
if (!EVP_SignUpdate(&ctx, Msg, Msglen))
|
||||
goto error;
|
||||
if (!EVP_SignFinal(&ctx, sigbuf, (unsigned int *)&siglen, &pk))
|
||||
goto error;
|
||||
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
|
||||
fputs("S = ", out);
|
||||
|
||||
for (i = 0; i < siglen; i++)
|
||||
fprintf(out, "%02X", sigbuf[i]);
|
||||
|
||||
fputs("\n", out);
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,351 @@
|
||||
/* fips_rsavtest.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#ifndef OPENSSL_FIPS
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("No FIPS RSA support\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# include <openssl/rsa.h>
|
||||
|
||||
# include "fips_utl.h"
|
||||
|
||||
int rsa_test(FILE *out, FILE *in, int saltlen);
|
||||
static int rsa_printver(FILE *out,
|
||||
BIGNUM *n, BIGNUM *e,
|
||||
const EVP_MD *dgst,
|
||||
unsigned char *Msg, long Msglen,
|
||||
unsigned char *S, long Slen, int Saltlen);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *in = NULL, *out = NULL;
|
||||
|
||||
int ret = 1;
|
||||
int Saltlen = -1;
|
||||
|
||||
if (!FIPS_mode_set(1)) {
|
||||
do_print_errors();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((argc > 2) && !strcmp("-saltlen", argv[1])) {
|
||||
Saltlen = atoi(argv[2]);
|
||||
if (Saltlen < 0) {
|
||||
fprintf(stderr, "FATAL: Invalid salt length\n");
|
||||
goto end;
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
} else if ((argc > 1) && !strcmp("-x931", argv[1])) {
|
||||
Saltlen = -2;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
in = stdin;
|
||||
else
|
||||
in = fopen(argv[1], "r");
|
||||
|
||||
if (argc < 2)
|
||||
out = stdout;
|
||||
else
|
||||
out = fopen(argv[2], "w");
|
||||
|
||||
if (!in) {
|
||||
fprintf(stderr, "FATAL input initialization error\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!out) {
|
||||
fprintf(stderr, "FATAL output initialization error\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!rsa_test(out, in, Saltlen)) {
|
||||
fprintf(stderr, "FATAL RSAVTEST file processing error\n");
|
||||
goto end;
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
|
||||
if (ret)
|
||||
do_print_errors();
|
||||
|
||||
if (in && (in != stdin))
|
||||
fclose(in);
|
||||
if (out && (out != stdout))
|
||||
fclose(out);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
# define RSA_TEST_MAXLINELEN 10240
|
||||
|
||||
int rsa_test(FILE *out, FILE *in, int Saltlen)
|
||||
{
|
||||
char *linebuf, *olinebuf, *p, *q;
|
||||
char *keyword, *value;
|
||||
const EVP_MD *dgst = NULL;
|
||||
BIGNUM *n = NULL, *e = NULL;
|
||||
unsigned char *Msg = NULL, *S = NULL;
|
||||
long Msglen, Slen;
|
||||
int ret = 0;
|
||||
int lnum = 0;
|
||||
|
||||
olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
|
||||
linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
|
||||
|
||||
if (!linebuf || !olinebuf)
|
||||
goto error;
|
||||
|
||||
while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) {
|
||||
lnum++;
|
||||
strcpy(linebuf, olinebuf);
|
||||
keyword = linebuf;
|
||||
/* Skip leading space */
|
||||
while (isspace((unsigned char)*keyword))
|
||||
keyword++;
|
||||
|
||||
/* Look for = sign */
|
||||
p = strchr(linebuf, '=');
|
||||
|
||||
/*
|
||||
* If no = or starts with [ (for [foo = bar] line) just copy
|
||||
*/
|
||||
if (!p || *keyword == '[') {
|
||||
if (fputs(olinebuf, out) < 0)
|
||||
goto error;
|
||||
continue;
|
||||
}
|
||||
|
||||
q = p - 1;
|
||||
|
||||
/* Remove trailing space */
|
||||
while (isspace((unsigned char)*q))
|
||||
*q-- = 0;
|
||||
|
||||
*p = 0;
|
||||
value = p + 1;
|
||||
|
||||
/* Remove leading space from value */
|
||||
while (isspace((unsigned char)*value))
|
||||
value++;
|
||||
|
||||
/* Remove trailing space from value */
|
||||
p = value + strlen(value) - 1;
|
||||
|
||||
while (*p == '\n' || isspace((unsigned char)*p))
|
||||
*p-- = 0;
|
||||
|
||||
if (!strcmp(keyword, "n")) {
|
||||
if (!do_hex2bn(&n, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "e")) {
|
||||
if (!do_hex2bn(&e, value))
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "SHAAlg")) {
|
||||
if (!strcmp(value, "SHA1"))
|
||||
dgst = EVP_sha1();
|
||||
else if (!strcmp(value, "SHA224"))
|
||||
dgst = EVP_sha224();
|
||||
else if (!strcmp(value, "SHA256"))
|
||||
dgst = EVP_sha256();
|
||||
else if (!strcmp(value, "SHA384"))
|
||||
dgst = EVP_sha384();
|
||||
else if (!strcmp(value, "SHA512"))
|
||||
dgst = EVP_sha512();
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"FATAL: unsupported algorithm \"%s\"\n", value);
|
||||
goto parse_error;
|
||||
}
|
||||
} else if (!strcmp(keyword, "Msg")) {
|
||||
if (Msg)
|
||||
goto parse_error;
|
||||
if (strlen(value) & 1)
|
||||
*(--value) = '0';
|
||||
Msg = hex2bin_m(value, &Msglen);
|
||||
if (!Msg)
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "S")) {
|
||||
if (S)
|
||||
goto parse_error;
|
||||
if (strlen(value) & 1)
|
||||
*(--value) = '0';
|
||||
S = hex2bin_m(value, &Slen);
|
||||
if (!S)
|
||||
goto parse_error;
|
||||
} else if (!strcmp(keyword, "Result"))
|
||||
continue;
|
||||
else
|
||||
goto parse_error;
|
||||
|
||||
fputs(olinebuf, out);
|
||||
|
||||
if (n && e && Msg && S && dgst) {
|
||||
if (!rsa_printver(out, n, e, dgst, Msg, Msglen, S, Slen, Saltlen))
|
||||
goto error;
|
||||
OPENSSL_free(Msg);
|
||||
Msg = NULL;
|
||||
OPENSSL_free(S);
|
||||
S = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
|
||||
if (olinebuf)
|
||||
OPENSSL_free(olinebuf);
|
||||
if (linebuf)
|
||||
OPENSSL_free(linebuf);
|
||||
if (n)
|
||||
BN_free(n);
|
||||
if (e)
|
||||
BN_free(e);
|
||||
|
||||
return ret;
|
||||
|
||||
parse_error:
|
||||
|
||||
fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
|
||||
|
||||
goto error;
|
||||
|
||||
}
|
||||
|
||||
static int rsa_printver(FILE *out,
|
||||
BIGNUM *n, BIGNUM *e,
|
||||
const EVP_MD *dgst,
|
||||
unsigned char *Msg, long Msglen,
|
||||
unsigned char *S, long Slen, int Saltlen)
|
||||
{
|
||||
int ret = 0, r;
|
||||
/* Setup RSA and EVP_PKEY structures */
|
||||
RSA *rsa_pubkey = NULL;
|
||||
EVP_PKEY pk;
|
||||
EVP_MD_CTX ctx;
|
||||
unsigned char *buf = NULL;
|
||||
rsa_pubkey = FIPS_rsa_new();
|
||||
if (!rsa_pubkey)
|
||||
goto error;
|
||||
rsa_pubkey->n = BN_dup(n);
|
||||
rsa_pubkey->e = BN_dup(e);
|
||||
if (!rsa_pubkey->n || !rsa_pubkey->e)
|
||||
goto error;
|
||||
pk.type = EVP_PKEY_RSA;
|
||||
pk.pkey.rsa = rsa_pubkey;
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
if (Saltlen >= 0) {
|
||||
M_EVP_MD_CTX_set_flags(&ctx,
|
||||
EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16));
|
||||
} else if (Saltlen == -2)
|
||||
M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931);
|
||||
if (!EVP_VerifyInit_ex(&ctx, dgst, NULL))
|
||||
goto error;
|
||||
if (!EVP_VerifyUpdate(&ctx, Msg, Msglen))
|
||||
goto error;
|
||||
|
||||
r = EVP_VerifyFinal(&ctx, S, Slen, &pk);
|
||||
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
|
||||
if (r < 0)
|
||||
goto error;
|
||||
ERR_clear_error();
|
||||
|
||||
if (r == 0)
|
||||
fputs("Result = F\n", out);
|
||||
else
|
||||
fputs("Result = P\n", out);
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
if (rsa_pubkey)
|
||||
FIPS_rsa_free(rsa_pubkey);
|
||||
if (buf)
|
||||
OPENSSL_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/fips.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
static char test[][60] = {
|
||||
"",
|
||||
"abc",
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
};
|
||||
|
||||
static const unsigned char ret[][SHA_DIGEST_LENGTH] = {
|
||||
{0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
|
||||
0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09},
|
||||
{0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
|
||||
0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d},
|
||||
{0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae,
|
||||
0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1},
|
||||
};
|
||||
|
||||
void FIPS_corrupt_sha1()
|
||||
{
|
||||
test[2][0]++;
|
||||
}
|
||||
|
||||
int FIPS_selftest_sha1()
|
||||
{
|
||||
size_t n;
|
||||
|
||||
for (n = 0; n < sizeof(test) / sizeof(test[0]); ++n) {
|
||||
unsigned char md[SHA_DIGEST_LENGTH];
|
||||
|
||||
EVP_Digest(test[n], strlen(test[n]), md, NULL, EVP_sha1(), NULL);
|
||||
if (memcmp(md, ret[n], sizeof md)) {
|
||||
FIPSerr(FIPS_F_FIPS_SELFTEST_SHA1, FIPS_R_SELFTEST_FAILED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user