Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c8ff30cbe7 | |||
| 0686c09eea | |||
| b18cb6a5d0 | |||
| 42329a828b | |||
| 8b487b73aa | |||
| 67bb45f44b | |||
| faa539f877 | |||
| ebcb5beb19 | |||
| 107d4388cb | |||
| cbfd3c044c | |||
| 0c05c37f93 | |||
| 519118f984 | |||
| a5f1b38de5 | |||
| 7e9949c30b | |||
| 17eeb9820c | |||
| 6bb507bc9c | |||
| e94ec3f85b | |||
| 79bc7a3212 | |||
| 643b77e644 | |||
| 053a8f728e | |||
| 8d979e5430 | |||
| b0ad3d74db | |||
| 43ea204db7 | |||
| d1c0de6fe0 | |||
| f368c73826 | |||
| fef78b0356 | |||
| a507617e4d | |||
| 764ab9802e | |||
| a0ba400c33 | |||
| ccbb165d98 | |||
| 8c26d750e1 | |||
| 7a60ca095d | |||
| 0f5d7d3f04 | |||
| 95321e15f2 | |||
| bbfe603519 | |||
| fc2d78dd1e | |||
| 681eb6ac2d | |||
| 32c8927159 | |||
| 81a191dc4d | |||
| 94cf5d030f | |||
| e000440982 | |||
| ca307ab6a3 | |||
| 065d733c4b | |||
| 2a0707210a | |||
| 246eeee61a | |||
| 794cc59e25 | |||
| 02084ea398 | |||
| 3cb12467cc | |||
| 7ce10d5da7 | |||
| 4784b99bf3 | |||
| 7d2dbc3791 | |||
| e3843d41b9 | |||
| f466cdb5e0 | |||
| bbf4246546 | |||
| 8cd7bbf514 | |||
| 3cb047e56c | |||
| 2d85062c4f | |||
| f35e8384a8 | |||
| 7179e53ea6 | |||
| 1d4fa785bc | |||
| cfb9d147bb | |||
| c90ed1901d | |||
| 96e744c176 | |||
| 9292632c8d | |||
| 5e2d0c929c | |||
| 57e81e666a | |||
| cedc6f1824 | |||
| d851842228 | |||
| aea20c15c9 | |||
| 5c12778948 | |||
| 2d05568a7b | |||
| fd67f61bb4 | |||
| 5916207dd3 | |||
| 8c6467976c | |||
| eb3028847e | |||
| 2ddc461a3f | |||
| 6a53b99f34 | |||
| 076c6a3389 | |||
| aefc6b27e1 | |||
| b228541129 | |||
| 73812e06b0 | |||
| edb729959f | |||
| 3c8652d0c6 | |||
| 438229a8d7 | |||
| 48e1d180a4 | |||
| 2070f8ad91 | |||
| 707af294a8 | |||
| 4c341d0299 | |||
| be49706c42 | |||
| 93103177a5 | |||
| 91222b8d38 | |||
| 6ad20dc912 | |||
| 130d529b71 | |||
| d04ca95356 | |||
| c77ea04c81 | |||
| 35ac5b7500 | |||
| fe36672bf5 | |||
| 0cade989e7 | |||
| b6473199a3 | |||
| 54689ed91e | |||
| ab1d28e305 | |||
| 8ebeabf0e2 | |||
| f29c429324 | |||
| f465461062 | |||
| 924a352d1b | |||
| 9ea9f9ce51 | |||
| d6c22ee938 | |||
| 919d8cf94e | |||
| 84cd49385c | |||
| a58baaf9e6 | |||
| ad8f5e1de9 | |||
| 7dd4e429a5 | |||
| 11c82895d7 | |||
| 7e42999122 | |||
| 39425b0f36 | |||
| d5c565a98d | |||
| 94a62e61aa | |||
| 2a3b3439c8 | |||
| 415c010d4a | |||
| 0bdef09263 | |||
| 34b4c829fd | |||
| 2ff7933f22 | |||
| 0d3c96337a | |||
| 591f251bf3 | |||
| ba9557d0ef | |||
| 218f51bcef | |||
| 898be92b67 |
+2
-2
@@ -221,8 +221,8 @@ if (ASAN)
|
||||
message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(OPENSSL_NO_ASM "1")
|
||||
endif()
|
||||
|
||||
|
||||
+1
-1
@@ -80,5 +80,5 @@ If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora
|
||||
|
||||
```
|
||||
cd fuzz
|
||||
./refresh_fuzzer_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
|
||||
./refresh_ssl_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
|
||||
```
|
||||
|
||||
@@ -227,6 +227,7 @@ parameter.
|
||||
`SSL_CTRL_OPTIONS` | `SSL_CTX_get_options` or `SSL_CTX_set_options`
|
||||
`SSL_CTRL_SESS_NUMBER` | `SSL_CTX_sess_number`
|
||||
`SSL_CTRL_SET_CURVES` | `SSL_CTX_set1_curves`
|
||||
`SSL_CTRL_SET_ECDH_AUTO` | `SSL_CTX_set_ecdh_auto`
|
||||
`SSL_CTRL_SET_MAX_CERT_LIST` | `SSL_CTX_set_max_cert_list`
|
||||
`SSL_CTRL_SET_MAX_SEND_FRAGMENT` | `SSL_CTX_set_max_send_fragment`
|
||||
`SSL_CTRL_SET_MSG_CALLBACK` | `SSL_set_msg_callback`
|
||||
|
||||
+8
-11
@@ -176,17 +176,6 @@ if(NOT MSVC AND NOT ANDROID)
|
||||
target_link_libraries(crypto pthread)
|
||||
endif()
|
||||
|
||||
add_executable(
|
||||
constant_time_test
|
||||
|
||||
constant_time_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(constant_time_test crypto)
|
||||
add_dependencies(all_tests constant_time_test)
|
||||
|
||||
add_executable(
|
||||
thread_test
|
||||
|
||||
@@ -211,11 +200,16 @@ add_dependencies(all_tests refcount_test)
|
||||
add_executable(
|
||||
crypto_test
|
||||
|
||||
asn1/asn1_test.cc
|
||||
bio/bio_test.cc
|
||||
chacha/chacha_test.cc
|
||||
constant_time_test.cc
|
||||
curve25519/x25519_test.cc
|
||||
dh/dh_test.cc
|
||||
dsa/dsa_test.cc
|
||||
ec/ec_test.cc
|
||||
err/err_test.cc
|
||||
evp/evp_extra_test.cc
|
||||
rsa/rsa_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:gtest_main>
|
||||
@@ -223,4 +217,7 @@ add_executable(
|
||||
)
|
||||
|
||||
target_link_libraries(crypto_test crypto gtest)
|
||||
if (WIN32)
|
||||
target_link_libraries(crypto_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests crypto_test)
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
#!/usr/bin/env perl
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||
@@ -731,6 +738,7 @@ $code.=<<___;
|
||||
.thumb
|
||||
#else
|
||||
.code 32
|
||||
# undef __thumb2__
|
||||
#endif
|
||||
|
||||
.type _bsaes_decrypt8,%function
|
||||
@@ -1357,7 +1365,7 @@ bsaes_cbc_encrypt:
|
||||
vmov @XMM[4],@XMM[15] @ just in case ensure that IV
|
||||
vmov @XMM[5],@XMM[0] @ and input are preserved
|
||||
bl AES_decrypt
|
||||
vld1.8 {@XMM[0]}, [$fp,:64] @ load result
|
||||
vld1.8 {@XMM[0]}, [$fp] @ load result
|
||||
veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV
|
||||
vmov @XMM[15], @XMM[5] @ @XMM[5] holds input
|
||||
vst1.8 {@XMM[0]}, [$rounds] @ write output
|
||||
|
||||
@@ -36,17 +36,4 @@ add_library(
|
||||
tasn_typ.c
|
||||
tasn_utl.c
|
||||
time_support.c
|
||||
x_bignum.c
|
||||
x_long.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
asn1_test
|
||||
|
||||
asn1_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(asn1_test crypto)
|
||||
add_dependencies(all_tests asn1_test)
|
||||
|
||||
+17
-9
@@ -114,7 +114,7 @@ int ASN1_TIME_check(ASN1_TIME *t)
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret;
|
||||
ASN1_GENERALIZEDTIME *ret = NULL;
|
||||
char *str;
|
||||
int newlen;
|
||||
|
||||
@@ -123,22 +123,21 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
|
||||
if (!out || !*out) {
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new()))
|
||||
return NULL;
|
||||
if (out)
|
||||
*out = ret;
|
||||
} else
|
||||
goto err;
|
||||
} else {
|
||||
ret = *out;
|
||||
}
|
||||
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME) {
|
||||
if (!ASN1_STRING_set(ret, t->data, t->length))
|
||||
return NULL;
|
||||
return ret;
|
||||
goto err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
return NULL;
|
||||
goto err;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
@@ -150,9 +149,18 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
return ret;
|
||||
done:
|
||||
if (out != NULL && *out == NULL)
|
||||
*out = ret;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (out == NULL || *out != ret)
|
||||
ASN1_GENERALIZEDTIME_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
|
||||
+12
-29
@@ -14,10 +14,13 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
// kTag128 is an ASN.1 structure with a universal tag with number 128.
|
||||
static const uint8_t kTag128[] = {
|
||||
@@ -38,42 +41,22 @@ static const uint8_t kTagOverflow[] = {
|
||||
0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
|
||||
};
|
||||
|
||||
static bool TestLargeTags() {
|
||||
TEST(ASN1Test, LargeTags) {
|
||||
const uint8_t *p = kTag258;
|
||||
bssl::UniquePtr<ASN1_TYPE> obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
|
||||
if (obj) {
|
||||
fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type);
|
||||
return false;
|
||||
}
|
||||
EXPECT_FALSE(obj) << "Parsed value with illegal tag" << obj->type;
|
||||
ERR_clear_error();
|
||||
|
||||
p = kTagOverflow;
|
||||
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow)));
|
||||
if (obj) {
|
||||
fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type);
|
||||
return false;
|
||||
}
|
||||
EXPECT_FALSE(obj) << "Parsed value with tag overflow" << obj->type;
|
||||
ERR_clear_error();
|
||||
|
||||
p = kTag128;
|
||||
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128)));
|
||||
if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 ||
|
||||
obj->value.asn1_string->data[0] != 0) {
|
||||
fprintf(stderr, "Failed to parse value with tag 128.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestLargeTags()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
ASSERT_TRUE(obj);
|
||||
EXPECT_EQ(128, obj->type);
|
||||
const uint8_t kZero = 0;
|
||||
EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
|
||||
obj->value.asn1_string->length));
|
||||
}
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/* 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 <openssl/asn1.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/*
|
||||
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
|
||||
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
|
||||
* since all BIGNUMs used are non negative and anything that looks negative
|
||||
* is normally due to an encoding error.
|
||||
*/
|
||||
|
||||
#define BN_SENSITIVE 1
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
||||
NULL, 0,
|
||||
bn_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_c2i,
|
||||
bn_i2c,
|
||||
NULL /* prim_print */ ,
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(BIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
||||
ASN1_ITEM_end(BIGNUM)
|
||||
|
||||
ASN1_ITEM_start(CBIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
|
||||
ASN1_ITEM_end(CBIGNUM)
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*pval = (ASN1_VALUE *)BN_new();
|
||||
if (*pval)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
if (!*pval)
|
||||
return;
|
||||
if (it->size & BN_SENSITIVE)
|
||||
BN_clear_free((BIGNUM *)*pval);
|
||||
else
|
||||
BN_free((BIGNUM *)*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
int pad;
|
||||
if (!*pval)
|
||||
return -1;
|
||||
bn = (BIGNUM *)*pval;
|
||||
/* If MSB set in an octet we need a padding byte */
|
||||
if (BN_num_bits(bn) & 0x7)
|
||||
pad = 0;
|
||||
else
|
||||
pad = 1;
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = 0;
|
||||
BN_bn2bin(bn, cont);
|
||||
}
|
||||
return pad + BN_num_bytes(bn);
|
||||
}
|
||||
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
if (!*pval) {
|
||||
if (!bn_new(pval, it)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bn = (BIGNUM *)*pval;
|
||||
if (!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/* 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 <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Custom primitive type for long handling. This converts between an
|
||||
* ASN1_INTEGER and a long directly.
|
||||
*/
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS long_pf = {
|
||||
NULL, 0,
|
||||
long_new,
|
||||
long_free,
|
||||
long_free, /* Clear should set to initial value */
|
||||
long_c2i,
|
||||
long_i2c,
|
||||
long_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(LONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
|
||||
ASN1_ITEM_end(LONG)
|
||||
|
||||
ASN1_ITEM_start(ZLONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
|
||||
ASN1_ITEM_end(ZLONG)
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
}
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
long ltmp;
|
||||
unsigned long utmp;
|
||||
int clen, pad, i;
|
||||
/* this exists to bypass broken gcc optimization */
|
||||
char *cp = (char *)pval;
|
||||
|
||||
/* use memcpy, because we may not be long aligned */
|
||||
OPENSSL_memcpy(<mp, cp, sizeof(long));
|
||||
|
||||
if (ltmp == it->size)
|
||||
return -1;
|
||||
/*
|
||||
* Convert the long to positive: we subtract one if negative so we can
|
||||
* cleanly handle the padding if only the MSB of the leading octet is
|
||||
* set.
|
||||
*/
|
||||
if (ltmp < 0)
|
||||
utmp = -ltmp - 1;
|
||||
else
|
||||
utmp = ltmp;
|
||||
clen = BN_num_bits_word(utmp);
|
||||
/* If MSB of leading octet set we need to pad */
|
||||
if (!(clen & 0x7))
|
||||
pad = 1;
|
||||
else
|
||||
pad = 0;
|
||||
|
||||
/* Convert number of bits to number of octets */
|
||||
clen = (clen + 7) >> 3;
|
||||
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = (ltmp < 0) ? 0xff : 0;
|
||||
for (i = clen - 1; i >= 0; i--) {
|
||||
cont[i] = (unsigned char)(utmp & 0xff);
|
||||
if (ltmp < 0)
|
||||
cont[i] ^= 0xff;
|
||||
utmp >>= 8;
|
||||
}
|
||||
}
|
||||
return clen + pad;
|
||||
}
|
||||
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
int neg, i;
|
||||
long ltmp;
|
||||
unsigned long utmp = 0;
|
||||
char *cp = (char *)pval;
|
||||
if (len > (int)sizeof(long)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
/* Is it negative? */
|
||||
if (len && (cont[0] & 0x80))
|
||||
neg = 1;
|
||||
else
|
||||
neg = 0;
|
||||
utmp = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
utmp <<= 8;
|
||||
if (neg)
|
||||
utmp |= cont[i] ^ 0xff;
|
||||
else
|
||||
utmp |= cont[i];
|
||||
}
|
||||
ltmp = (long)utmp;
|
||||
if (neg) {
|
||||
ltmp++;
|
||||
ltmp = -ltmp;
|
||||
}
|
||||
if (ltmp == it->size) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(cp, <mp, sizeof(long));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
return BIO_printf(out, "%ld\n", *(long *)pval);
|
||||
}
|
||||
@@ -16,17 +16,3 @@ add_library(
|
||||
socket.c
|
||||
socket_helper.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
bio_test
|
||||
|
||||
bio_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(bio_test crypto)
|
||||
if (WIN32)
|
||||
target_link_libraries(bio_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests bio_test)
|
||||
|
||||
+207
-318
@@ -16,7 +16,18 @@
|
||||
#define _POSIX_C_SOURCE 201410L
|
||||
#endif
|
||||
|
||||
#include <openssl/base.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <arpa/inet.h>
|
||||
@@ -33,27 +44,15 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
|
||||
static void PrintSocketError(const char *func) {
|
||||
perror(func);
|
||||
}
|
||||
static int closesocket(int sock) { return close(sock); }
|
||||
static std::string LastSocketError() { return strerror(errno); }
|
||||
#else
|
||||
static void PrintSocketError(const char *func) {
|
||||
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
|
||||
static std::string LastSocketError() {
|
||||
char buf[DECIMAL_SIZE(int) + 1];
|
||||
BIO_snprintf(buf, sizeof(buf), "%d", WSAGetLastError());
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -68,356 +67,246 @@ class ScopedSocket {
|
||||
const int sock_;
|
||||
};
|
||||
|
||||
static bool TestSocketConnect() {
|
||||
TEST(BIOTest, SocketConnect) {
|
||||
static const char kTestMessage[] = "test";
|
||||
|
||||
// Set up a listening socket on localhost.
|
||||
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (listening_sock == -1) {
|
||||
PrintSocketError("socket");
|
||||
return false;
|
||||
}
|
||||
ASSERT_NE(-1, listening_sock) << LastSocketError();
|
||||
ScopedSocket listening_sock_closer(listening_sock);
|
||||
|
||||
struct sockaddr_in sin;
|
||||
OPENSSL_memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
|
||||
PrintSocketError("inet_pton");
|
||||
return false;
|
||||
}
|
||||
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
|
||||
PrintSocketError("bind");
|
||||
return false;
|
||||
}
|
||||
if (listen(listening_sock, 1)) {
|
||||
PrintSocketError("listen");
|
||||
return false;
|
||||
}
|
||||
ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr))
|
||||
<< LastSocketError();
|
||||
ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)))
|
||||
<< LastSocketError();
|
||||
ASSERT_EQ(0, listen(listening_sock, 1)) << LastSocketError();
|
||||
socklen_t sockaddr_len = sizeof(sin);
|
||||
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
|
||||
sockaddr_len != sizeof(sin)) {
|
||||
PrintSocketError("getsockname");
|
||||
return false;
|
||||
}
|
||||
ASSERT_EQ(0,
|
||||
getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len))
|
||||
<< LastSocketError();
|
||||
// The Android NDK, contrary to POSIX, makes |socklen_t| signed.
|
||||
ASSERT_EQ(sizeof(sin), static_cast<size_t>(sockaddr_len));
|
||||
|
||||
// Connect to it with a connect BIO.
|
||||
char hostname[80];
|
||||
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
|
||||
ntohs(sin.sin_port));
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_connect(hostname));
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new_connect failed.\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(bio);
|
||||
|
||||
if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
|
||||
sizeof(kTestMessage)) {
|
||||
fprintf(stderr, "BIO_write failed.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
// Write a test message to the BIO.
|
||||
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
|
||||
BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)));
|
||||
|
||||
// Accept the socket.
|
||||
int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
|
||||
if (sock == -1) {
|
||||
PrintSocketError("accept");
|
||||
return false;
|
||||
}
|
||||
ASSERT_NE(-1, sock) << LastSocketError();
|
||||
ScopedSocket sock_closer(sock);
|
||||
|
||||
char buf[5];
|
||||
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
|
||||
PrintSocketError("read");
|
||||
return false;
|
||||
}
|
||||
if (OPENSSL_memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Check the same message is read back out.
|
||||
char buf[sizeof(kTestMessage)];
|
||||
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
|
||||
recv(sock, buf, sizeof(buf), 0))
|
||||
<< LastSocketError();
|
||||
EXPECT_EQ(Bytes(kTestMessage, sizeof(kTestMessage)), Bytes(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
static bool TestPrintf() {
|
||||
TEST(BIOTest, Printf) {
|
||||
// Test a short output, a very long one, and various sizes around
|
||||
// 256 (the size of the buffer) to ensure edge cases are correct.
|
||||
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
|
||||
static const size_t kLengths[] = {5, 250, 251, 252, 253, 254, 1023};
|
||||
|
||||
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new failed\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(bio);
|
||||
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kLengths); i++) {
|
||||
char string[1024];
|
||||
if (kLengths[i] >= sizeof(string)) {
|
||||
fprintf(stderr, "Bad test string length\n");
|
||||
return false;
|
||||
}
|
||||
OPENSSL_memset(string, 'a', sizeof(string));
|
||||
string[kLengths[i]] = '\0';
|
||||
for (size_t length : kLengths) {
|
||||
SCOPED_TRACE(length);
|
||||
|
||||
std::string in(length, 'a');
|
||||
|
||||
int ret = BIO_printf(bio.get(), "test %s", in.c_str());
|
||||
ASSERT_GE(ret, 0);
|
||||
EXPECT_EQ(5 + length, static_cast<size_t>(ret));
|
||||
|
||||
int ret = BIO_printf(bio.get(), "test %s", string);
|
||||
if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
|
||||
fprintf(stderr, "BIO_printf failed: %d\n", ret);
|
||||
return false;
|
||||
}
|
||||
const uint8_t *contents;
|
||||
size_t len;
|
||||
if (!BIO_mem_contents(bio.get(), &contents, &len)) {
|
||||
fprintf(stderr, "BIO_mem_contents failed\n");
|
||||
return false;
|
||||
}
|
||||
if (len != 5 + kLengths[i] ||
|
||||
strncmp((const char *)contents, "test ", 5) != 0 ||
|
||||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
|
||||
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
|
||||
EXPECT_EQ("test " + in,
|
||||
std::string(reinterpret_cast<const char *>(contents), len));
|
||||
|
||||
if (!BIO_reset(bio.get())) {
|
||||
fprintf(stderr, "BIO_reset failed\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(BIO_reset(bio.get()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
|
||||
size_t expected_len, size_t max_len) {
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(data, data_len));
|
||||
static const size_t kLargeASN1PayloadLen = 8000;
|
||||
|
||||
struct ASN1TestParam {
|
||||
bool should_succeed;
|
||||
std::vector<uint8_t> input;
|
||||
// suffix_len is the number of zeros to append to |input|.
|
||||
size_t suffix_len;
|
||||
// expected_len, if |should_succeed| is true, is the expected length of the
|
||||
// ASN.1 element.
|
||||
size_t expected_len;
|
||||
size_t max_len;
|
||||
} kASN1TestParams[] = {
|
||||
{true, {0x30, 2, 1, 2, 0, 0}, 0, 4, 100},
|
||||
{false /* truncated */, {0x30, 3, 1, 2}, 0, 0, 100},
|
||||
{false /* should be short len */, {0x30, 0x81, 1, 1}, 0, 0, 100},
|
||||
{false /* zero padded */, {0x30, 0x82, 0, 1, 1}, 0, 0, 100},
|
||||
|
||||
// Test a large payload.
|
||||
{true,
|
||||
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
|
||||
kLargeASN1PayloadLen,
|
||||
4 + kLargeASN1PayloadLen,
|
||||
kLargeASN1PayloadLen * 2},
|
||||
{false /* max_len too short */,
|
||||
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
|
||||
kLargeASN1PayloadLen,
|
||||
4 + kLargeASN1PayloadLen,
|
||||
3 + kLargeASN1PayloadLen},
|
||||
|
||||
// Test an indefinite-length input.
|
||||
{true,
|
||||
{0x30, 0x80},
|
||||
kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 2,
|
||||
kLargeASN1PayloadLen * 2},
|
||||
{false /* max_len too short */,
|
||||
{0x30, 0x80},
|
||||
kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 1},
|
||||
};
|
||||
|
||||
class BIOASN1Test : public testing::TestWithParam<ASN1TestParam> {};
|
||||
|
||||
TEST_P(BIOASN1Test, ReadASN1) {
|
||||
const ASN1TestParam& param = GetParam();
|
||||
std::vector<uint8_t> input = param.input;
|
||||
input.resize(input.size() + param.suffix_len, 0);
|
||||
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(input.data(), input.size()));
|
||||
ASSERT_TRUE(bio);
|
||||
|
||||
uint8_t *out;
|
||||
size_t out_len;
|
||||
int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
|
||||
int ok = BIO_read_asn1(bio.get(), &out, &out_len, param.max_len);
|
||||
if (!ok) {
|
||||
out = nullptr;
|
||||
}
|
||||
bssl::UniquePtr<uint8_t> out_storage(out);
|
||||
|
||||
if (should_succeed != (ok == 1)) {
|
||||
return false;
|
||||
ASSERT_EQ(param.should_succeed, (ok == 1));
|
||||
if (param.should_succeed) {
|
||||
EXPECT_EQ(Bytes(input.data(), param.expected_len), Bytes(out, out_len));
|
||||
}
|
||||
|
||||
if (should_succeed && (out_len != expected_len ||
|
||||
OPENSSL_memcmp(data, out, expected_len) != 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestASN1() {
|
||||
static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
|
||||
static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */
|
||||
static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */
|
||||
static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */
|
||||
INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
|
||||
|
||||
if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
|
||||
!ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
|
||||
!ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
|
||||
!ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
|
||||
return false;
|
||||
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
|
||||
class BIOPairTest : public testing::TestWithParam<bool> {};
|
||||
|
||||
TEST_P(BIOPairTest, TestPair) {
|
||||
BIO *bio1, *bio2;
|
||||
ASSERT_TRUE(BIO_new_bio_pair(&bio1, 10, &bio2, 10));
|
||||
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
|
||||
|
||||
if (GetParam()) {
|
||||
std::swap(bio1, bio2);
|
||||
}
|
||||
|
||||
static const size_t kLargePayloadLen = 8000;
|
||||
static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
|
||||
kLargePayloadLen & 0xff};
|
||||
bssl::UniquePtr<uint8_t> large(reinterpret_cast<uint8_t *>(
|
||||
OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
|
||||
if (!large) {
|
||||
return false;
|
||||
}
|
||||
OPENSSL_memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
|
||||
OPENSSL_memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
|
||||
// Check initial states.
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen * 2)) {
|
||||
fprintf(stderr, "Large payload test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// Data written in one end may be read out the other.
|
||||
uint8_t buf[20];
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen - 1)) {
|
||||
fprintf(stderr, "max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// Attempting to write more than 10 bytes will write partially.
|
||||
EXPECT_EQ(10, BIO_write(bio1, "1234567890___", 13));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(-1, BIO_write(bio1, "z", 1));
|
||||
EXPECT_TRUE(BIO_should_write(bio1));
|
||||
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("1234567890"), Bytes(buf, 10));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
static const uint8_t kIndefPrefix[] = {0x30, 0x80};
|
||||
OPENSSL_memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen*2)) {
|
||||
fprintf(stderr, "indefinite length test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// Unsuccessful reads update the read request.
|
||||
EXPECT_EQ(-1, BIO_read(bio2, buf, 5));
|
||||
EXPECT_TRUE(BIO_should_read(bio2));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen-1)) {
|
||||
fprintf(stderr, "indefinite length, max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// The read request is clamped to the size of the buffer.
|
||||
EXPECT_EQ(-1, BIO_read(bio2, buf, 20));
|
||||
EXPECT_TRUE(BIO_should_read(bio2));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
return true;
|
||||
// Data may be written and read in chunks.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(5, BIO_write(bio1, "67890___", 8));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
|
||||
EXPECT_EQ(Bytes("123"), Bytes(buf, 3));
|
||||
EXPECT_EQ(3u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(7, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("4567890"), Bytes(buf, 7));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Successful reads reset the read request.
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
// Test writes and reads starting in the middle of the ring buffer and
|
||||
// wrapping to front.
|
||||
EXPECT_EQ(8, BIO_write(bio1, "abcdefgh", 8));
|
||||
EXPECT_EQ(2u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
|
||||
EXPECT_EQ(Bytes("abc"), Bytes(buf, 3));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(5, BIO_write(bio1, "ijklm___", 8));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("defghijklm"), Bytes(buf, 10));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Data may flow from both ends in parallel.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5, BIO_write(bio2, "67890", 5));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("67890"), Bytes(buf, 5));
|
||||
|
||||
// Closing the write end causes an EOF on the read half, after draining.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_TRUE(BIO_shutdown_wr(bio1));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
EXPECT_EQ(0, BIO_read(bio2, buf, sizeof(buf)));
|
||||
|
||||
// A closed write end may not be written to.
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(-1, BIO_write(bio1, "_____", 5));
|
||||
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_BIO, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(BIO_R_BROKEN_PIPE, ERR_GET_REASON(err));
|
||||
|
||||
// The other end is still functional.
|
||||
EXPECT_EQ(5, BIO_write(bio2, "12345", 5));
|
||||
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
}
|
||||
|
||||
static bool TestPair() {
|
||||
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
BIO *bio1, *bio2;
|
||||
if (!BIO_new_bio_pair(&bio1, 10, &bio2, 10)) {
|
||||
return false;
|
||||
}
|
||||
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
|
||||
|
||||
if (i == 1) {
|
||||
std::swap(bio1, bio2);
|
||||
}
|
||||
|
||||
// Check initial states.
|
||||
if (BIO_ctrl_get_write_guarantee(bio1) != 10 ||
|
||||
BIO_ctrl_get_read_request(bio1) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data written in one end may be read out the other.
|
||||
char buf[20];
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempting to write more than 10 bytes will write partially.
|
||||
if (BIO_write(bio1, "1234567890___", 13) != 10 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_write(bio1, "z", 1) != -1 ||
|
||||
!BIO_should_write(bio1) ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
|
||||
OPENSSL_memcmp(buf, "1234567890", 10) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unsuccessful reads update the read request.
|
||||
if (BIO_read(bio2, buf, 5) != -1 ||
|
||||
!BIO_should_read(bio2) ||
|
||||
BIO_ctrl_get_read_request(bio1) != 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The read request is clamped to the size of the buffer.
|
||||
if (BIO_read(bio2, buf, 20) != -1 ||
|
||||
!BIO_should_read(bio2) ||
|
||||
BIO_ctrl_get_read_request(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data may be written and read in chunks.
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
|
||||
BIO_write(bio1, "67890___", 8) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_read(bio2, buf, 3) != 3 ||
|
||||
OPENSSL_memcmp(buf, "123", 3) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 3 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 7 ||
|
||||
OPENSSL_memcmp(buf, "4567890", 7) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Successful reads reset the read request.
|
||||
if (BIO_ctrl_get_read_request(bio1) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test writes and reads starting in the middle of the ring buffer and
|
||||
// wrapping to front.
|
||||
if (BIO_write(bio1, "abcdefgh", 8) != 8 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 2 ||
|
||||
BIO_read(bio2, buf, 3) != 3 ||
|
||||
OPENSSL_memcmp(buf, "abc", 3) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
|
||||
BIO_write(bio1, "ijklm___", 8) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
|
||||
OPENSSL_memcmp(buf, "defghijklm", 10) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data may flow from both ends in parallel.
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
BIO_write(bio2, "67890", 5) != 5 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
|
||||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "67890", 5) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Closing the write end causes an EOF on the read half, after draining.
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
!BIO_shutdown_wr(bio1) ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A closed write end may not be written to.
|
||||
if (BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_write(bio1, "_____", 5) != -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t err = ERR_get_error();
|
||||
if (ERR_GET_LIB(err) != ERR_LIB_BIO ||
|
||||
ERR_GET_REASON(err) != BIO_R_BROKEN_PIPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The other end is still functional.
|
||||
if (BIO_write(bio2, "12345", 5) != 5 ||
|
||||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// Initialize Winsock.
|
||||
WORD wsa_version = MAKEWORD(2, 2);
|
||||
WSADATA wsa_data;
|
||||
int wsa_err = WSAStartup(wsa_version, &wsa_data);
|
||||
if (wsa_err != 0) {
|
||||
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
|
||||
return 1;
|
||||
}
|
||||
if (wsa_data.wVersion != wsa_version) {
|
||||
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!TestSocketConnect() ||
|
||||
!TestPrintf() ||
|
||||
!TestASN1() ||
|
||||
!TestPair()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true));
|
||||
|
||||
@@ -84,8 +84,8 @@ die "can't locate x86_64-xlate.pl";
|
||||
# output, so this isn't useful anyway.
|
||||
#
|
||||
# TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1.
|
||||
$avx = 0;
|
||||
$addx = 0;
|
||||
$avx = 2;
|
||||
$addx = 1;
|
||||
|
||||
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
|
||||
*STDOUT = *OUT;
|
||||
|
||||
+36
-15
@@ -125,6 +125,11 @@
|
||||
#define OPENSSL_BN_ASM_MONT
|
||||
#endif
|
||||
|
||||
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b,
|
||||
const BN_MONT_CTX *mont, BN_CTX *ctx);
|
||||
|
||||
|
||||
BN_MONT_CTX *BN_MONT_CTX_new(void) {
|
||||
BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
|
||||
|
||||
@@ -361,27 +366,43 @@ err:
|
||||
|
||||
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BN_MONT_CTX *mont, BN_CTX *ctx) {
|
||||
BIGNUM *tmp;
|
||||
int ret = 0;
|
||||
|
||||
#if defined(OPENSSL_BN_ASM_MONT)
|
||||
#if !defined(OPENSSL_BN_ASM_MONT)
|
||||
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
|
||||
#else
|
||||
int num = mont->N.top;
|
||||
|
||||
if (num > 1 && a->top == num && b->top == num) {
|
||||
if (bn_wexpand(r, num) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
|
||||
r->neg = a->neg ^ b->neg;
|
||||
r->top = num;
|
||||
bn_correct_top(r);
|
||||
return 1;
|
||||
}
|
||||
/* |bn_mul_mont| requires at least 128 bits of limbs, at least for x86. */
|
||||
if (num < (128 / BN_BITS2) ||
|
||||
a->top != num ||
|
||||
b->top != num) {
|
||||
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
|
||||
}
|
||||
|
||||
if (bn_wexpand(r, num) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
|
||||
/* The check above ensures this won't happen. */
|
||||
assert(0);
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
r->neg = a->neg ^ b->neg;
|
||||
r->top = num;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b,
|
||||
const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
int ret = 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
BIGNUM *tmp = BN_CTX_get(ctx);
|
||||
if (tmp == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
+4
-4
@@ -148,7 +148,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
}
|
||||
q->neg = 0;
|
||||
if (!BN_add_word(q, 1) ||
|
||||
!BN_mod_exp(ret, A, q, p, ctx)) {
|
||||
!BN_mod_exp_mont(ret, A, q, p, ctx, NULL)) {
|
||||
goto end;
|
||||
}
|
||||
err = 0;
|
||||
@@ -193,7 +193,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
goto end;
|
||||
}
|
||||
q->neg = 0;
|
||||
if (!BN_mod_exp(b, t, q, p, ctx)) {
|
||||
if (!BN_mod_exp_mont(b, t, q, p, ctx, NULL)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
|
||||
/* Now that we have some non-square, we can find an element
|
||||
* of order 2^e by computing its q'th power. */
|
||||
if (!BN_mod_exp(y, y, q, p, ctx)) {
|
||||
if (!BN_mod_exp_mont(y, y, q, p, ctx, NULL)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_is_one(y)) {
|
||||
@@ -327,7 +327,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!BN_mod_exp(x, A, t, p, ctx)) {
|
||||
if (!BN_mod_exp_mont(x, A, t, p, ctx, NULL)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_is_zero(x)) {
|
||||
|
||||
@@ -38,7 +38,7 @@ static int is_string_type(unsigned tag) {
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T16STRING:
|
||||
case CBS_ASN1_T61STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
|
||||
@@ -262,24 +262,24 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
|
||||
/* Remove CBC padding. Code from here on is timing-sensitive with respect to
|
||||
* |padding_ok| and |data_plus_mac_len| for CBC ciphers. */
|
||||
unsigned padding_ok, data_plus_mac_len;
|
||||
size_t padding_ok, data_plus_mac_len;
|
||||
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
|
||||
if (!EVP_tls_cbc_remove_padding(
|
||||
&padding_ok, &data_plus_mac_len, out, total,
|
||||
EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
|
||||
(unsigned)HMAC_size(&tls_ctx->hmac_ctx))) {
|
||||
HMAC_size(&tls_ctx->hmac_ctx))) {
|
||||
/* Publicly invalid. This can be rejected in non-constant time. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
padding_ok = ~0u;
|
||||
padding_ok = CONSTTIME_TRUE_S;
|
||||
data_plus_mac_len = total;
|
||||
/* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
|
||||
* already been checked against the MAC size at the top of the function. */
|
||||
assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
|
||||
}
|
||||
unsigned data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
|
||||
size_t data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
|
||||
|
||||
/* At this point, if the padding is valid, the first |data_plus_mac_len| bytes
|
||||
* after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is
|
||||
@@ -332,8 +332,8 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
* safe to simply perform the padding check first, but it would not be under a
|
||||
* different choice of MAC location on padding failure. See
|
||||
* EVP_tls_cbc_remove_padding. */
|
||||
unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len),
|
||||
0);
|
||||
size_t good =
|
||||
constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len), 0);
|
||||
good &= padding_ok;
|
||||
if (!good) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
|
||||
@@ -110,9 +110,9 @@ struct evp_aead_st {
|
||||
* If the function returns one, it runs in time independent of the contents of
|
||||
* |in|. It is also guaranteed that |*out_len| >= |mac_size|, satisfying
|
||||
* |EVP_tls_cbc_copy_mac|'s precondition. */
|
||||
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned block_size, unsigned mac_size);
|
||||
int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
size_t block_size, size_t mac_size);
|
||||
|
||||
/* EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first
|
||||
* |in_len| bytes of |in| to |out| in constant time (independent of the concrete
|
||||
@@ -122,9 +122,8 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
* On entry:
|
||||
* orig_len >= in_len >= md_size
|
||||
* md_size <= EVP_MAX_MD_SIZE */
|
||||
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned orig_len);
|
||||
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
|
||||
size_t in_len, size_t orig_len);
|
||||
|
||||
/* EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function
|
||||
* which EVP_tls_cbc_digest_record supports. */
|
||||
|
||||
+104
-102
@@ -73,20 +73,19 @@
|
||||
* supported by TLS.) */
|
||||
#define MAX_HASH_BLOCK_SIZE 128
|
||||
|
||||
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned block_size, unsigned mac_size) {
|
||||
unsigned padding_length, good, to_check, i;
|
||||
const unsigned overhead = 1 /* padding length byte */ + mac_size;
|
||||
int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
size_t block_size, size_t mac_size) {
|
||||
const size_t overhead = 1 /* padding length byte */ + mac_size;
|
||||
|
||||
/* These lengths are all public so we can test them in non-constant time. */
|
||||
if (overhead > in_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
padding_length = in[in_len - 1];
|
||||
size_t padding_length = in[in_len - 1];
|
||||
|
||||
good = constant_time_ge(in_len, overhead + padding_length);
|
||||
size_t good = constant_time_ge_s(in_len, overhead + padding_length);
|
||||
/* The padding consists of a length byte at the end of the record and
|
||||
* then that many bytes of padding, all with the same value as the
|
||||
* length byte. Thus, with the length byte included, there are i+1
|
||||
@@ -96,12 +95,12 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
* decrypted information. Therefore we always have to check the maximum
|
||||
* amount of padding possible. (Again, the length of the record is
|
||||
* public information so we can use it.) */
|
||||
to_check = 256; /* maximum amount of padding, inc length byte. */
|
||||
size_t to_check = 256; /* maximum amount of padding, inc length byte. */
|
||||
if (to_check > in_len) {
|
||||
to_check = in_len;
|
||||
}
|
||||
|
||||
for (i = 0; i < to_check; i++) {
|
||||
for (size_t i = 0; i < to_check; i++) {
|
||||
uint8_t mask = constant_time_ge_8(padding_length, i);
|
||||
uint8_t b = in[in_len - 1 - i];
|
||||
/* The final |padding_length+1| bytes should all have the value
|
||||
@@ -111,7 +110,7 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
|
||||
/* If any of the final |padding_length+1| bytes had the wrong value,
|
||||
* one or more of the lower eight bits of |good| will be cleared. */
|
||||
good = constant_time_eq(0xff, good & 0xff);
|
||||
good = constant_time_eq_s(0xff, good & 0xff);
|
||||
|
||||
/* Always treat |padding_length| as zero on error. If, assuming block size of
|
||||
* 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16
|
||||
@@ -123,16 +122,15 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned orig_len) {
|
||||
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
|
||||
size_t in_len, size_t orig_len) {
|
||||
uint8_t rotated_mac1[EVP_MAX_MD_SIZE], rotated_mac2[EVP_MAX_MD_SIZE];
|
||||
uint8_t *rotated_mac = rotated_mac1;
|
||||
uint8_t *rotated_mac_tmp = rotated_mac2;
|
||||
|
||||
/* mac_end is the index of |in| just after the end of the MAC. */
|
||||
unsigned mac_end = in_len;
|
||||
unsigned mac_start = mac_end - md_size;
|
||||
size_t mac_end = in_len;
|
||||
size_t mac_start = mac_end - md_size;
|
||||
|
||||
assert(orig_len >= in_len);
|
||||
assert(in_len >= md_size);
|
||||
@@ -140,20 +138,20 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
|
||||
/* scan_start contains the number of bytes that we can ignore because
|
||||
* the MAC's position can only vary by 255 bytes. */
|
||||
unsigned scan_start = 0;
|
||||
size_t scan_start = 0;
|
||||
/* This information is public so it's safe to branch based on it. */
|
||||
if (orig_len > md_size + 255 + 1) {
|
||||
scan_start = orig_len - (md_size + 255 + 1);
|
||||
}
|
||||
|
||||
unsigned rotate_offset = 0;
|
||||
size_t rotate_offset = 0;
|
||||
uint8_t mac_started = 0;
|
||||
OPENSSL_memset(rotated_mac, 0, md_size);
|
||||
for (unsigned i = scan_start, j = 0; i < orig_len; i++, j++) {
|
||||
for (size_t i = scan_start, j = 0; i < orig_len; i++, j++) {
|
||||
if (j >= md_size) {
|
||||
j -= md_size;
|
||||
}
|
||||
unsigned is_mac_start = constant_time_eq(i, mac_start);
|
||||
size_t is_mac_start = constant_time_eq_s(i, mac_start);
|
||||
mac_started |= is_mac_start;
|
||||
uint8_t mac_ended = constant_time_ge_8(i, mac_end);
|
||||
rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
|
||||
@@ -163,12 +161,11 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
|
||||
/* Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
|
||||
* position. */
|
||||
for (unsigned offset = 1; offset < md_size;
|
||||
offset <<= 1, rotate_offset >>= 1) {
|
||||
for (size_t offset = 1; offset < md_size; offset <<= 1, rotate_offset >>= 1) {
|
||||
/* Rotate by |offset| iff the corresponding bit is set in
|
||||
* |rotate_offset|, placing the result in |rotated_mac_tmp|. */
|
||||
const uint8_t skip_rotate = (rotate_offset & 1) - 1;
|
||||
for (unsigned i = 0, j = offset; i < md_size; i++, j++) {
|
||||
for (size_t i = 0, j = offset; i < md_size; i++, j++) {
|
||||
if (j >= md_size) {
|
||||
j -= md_size;
|
||||
}
|
||||
@@ -211,40 +208,49 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
*((p)++) = (uint8_t)((n)); \
|
||||
} while (0)
|
||||
|
||||
typedef union {
|
||||
SHA_CTX sha1;
|
||||
SHA256_CTX sha256;
|
||||
SHA512_CTX sha512;
|
||||
} HASH_CTX;
|
||||
|
||||
static void tls1_sha1_transform(HASH_CTX *ctx, const uint8_t *block) {
|
||||
SHA1_Transform(&ctx->sha1, block);
|
||||
}
|
||||
|
||||
static void tls1_sha256_transform(HASH_CTX *ctx, const uint8_t *block) {
|
||||
SHA256_Transform(&ctx->sha256, block);
|
||||
}
|
||||
|
||||
static void tls1_sha512_transform(HASH_CTX *ctx, const uint8_t *block) {
|
||||
SHA512_Transform(&ctx->sha512, block);
|
||||
}
|
||||
|
||||
/* These functions serialize the state of a hash and thus perform the standard
|
||||
* "final" operation without adding the padding and length that such a function
|
||||
* typically does. */
|
||||
static void tls1_sha1_final_raw(void *ctx, uint8_t *md_out) {
|
||||
SHA_CTX *sha1 = ctx;
|
||||
static void tls1_sha1_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
|
||||
SHA_CTX *sha1 = &ctx->sha1;
|
||||
u32toBE(sha1->h[0], md_out);
|
||||
u32toBE(sha1->h[1], md_out);
|
||||
u32toBE(sha1->h[2], md_out);
|
||||
u32toBE(sha1->h[3], md_out);
|
||||
u32toBE(sha1->h[4], md_out);
|
||||
}
|
||||
#define LARGEST_DIGEST_CTX SHA_CTX
|
||||
|
||||
static void tls1_sha256_final_raw(void *ctx, uint8_t *md_out) {
|
||||
SHA256_CTX *sha256 = ctx;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
static void tls1_sha256_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
|
||||
SHA256_CTX *sha256 = &ctx->sha256;
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
u32toBE(sha256->h[i], md_out);
|
||||
}
|
||||
}
|
||||
#undef LARGEST_DIGEST_CTX
|
||||
#define LARGEST_DIGEST_CTX SHA256_CTX
|
||||
|
||||
static void tls1_sha512_final_raw(void *ctx, uint8_t *md_out) {
|
||||
SHA512_CTX *sha512 = ctx;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
static void tls1_sha512_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
|
||||
SHA512_CTX *sha512 = &ctx->sha512;
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
u64toBE(sha512->h[i], md_out);
|
||||
}
|
||||
}
|
||||
#undef LARGEST_DIGEST_CTX
|
||||
#define LARGEST_DIGEST_CTX SHA512_CTX
|
||||
|
||||
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) {
|
||||
switch (EVP_MD_type(md)) {
|
||||
@@ -264,54 +270,42 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
size_t data_plus_mac_plus_padding_size,
|
||||
const uint8_t *mac_secret,
|
||||
unsigned mac_secret_length) {
|
||||
union {
|
||||
double align;
|
||||
uint8_t c[sizeof(LARGEST_DIGEST_CTX)];
|
||||
} md_state;
|
||||
void (*md_final_raw)(void *ctx, uint8_t *md_out);
|
||||
void (*md_transform)(void *ctx, const uint8_t *block);
|
||||
HASH_CTX md_state;
|
||||
void (*md_final_raw)(HASH_CTX *ctx, uint8_t *md_out);
|
||||
void (*md_transform)(HASH_CTX *ctx, const uint8_t *block);
|
||||
unsigned md_size, md_block_size = 64;
|
||||
unsigned len, max_mac_bytes, num_blocks, num_starting_blocks, k,
|
||||
mac_end_offset, c, index_a, index_b;
|
||||
unsigned int bits; /* at most 18 bits */
|
||||
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
|
||||
/* hmac_pad is the masked HMAC key. */
|
||||
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
|
||||
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
|
||||
uint8_t mac_out[EVP_MAX_MD_SIZE];
|
||||
unsigned i, j, md_out_size_u;
|
||||
EVP_MD_CTX md_ctx;
|
||||
/* mdLengthSize is the number of bytes in the length field that terminates
|
||||
* the hash. */
|
||||
/* md_length_size is the number of bytes in the length field that terminates
|
||||
* the hash. */
|
||||
unsigned md_length_size = 8;
|
||||
|
||||
/* This is a, hopefully redundant, check that allows us to forget about
|
||||
* many possible overflows later in this function. */
|
||||
assert(data_plus_mac_plus_padding_size < 1024 * 1024);
|
||||
/* Bound the acceptable input so we can forget about many possible overflows
|
||||
* later in this function. This is redundant with the record size limits in
|
||||
* TLS. */
|
||||
if (data_plus_mac_plus_padding_size >= 1024 * 1024) {
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (EVP_MD_type(md)) {
|
||||
case NID_sha1:
|
||||
SHA1_Init((SHA_CTX *)md_state.c);
|
||||
SHA1_Init(&md_state.sha1);
|
||||
md_final_raw = tls1_sha1_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const uint8_t *block))SHA1_Transform;
|
||||
md_size = 20;
|
||||
md_transform = tls1_sha1_transform;
|
||||
md_size = SHA_DIGEST_LENGTH;
|
||||
break;
|
||||
|
||||
case NID_sha256:
|
||||
SHA256_Init((SHA256_CTX *)md_state.c);
|
||||
SHA256_Init(&md_state.sha256);
|
||||
md_final_raw = tls1_sha256_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const uint8_t *block))SHA256_Transform;
|
||||
md_size = 32;
|
||||
md_transform = tls1_sha256_transform;
|
||||
md_size = SHA256_DIGEST_LENGTH;
|
||||
break;
|
||||
|
||||
case NID_sha384:
|
||||
SHA384_Init((SHA512_CTX *)md_state.c);
|
||||
SHA384_Init(&md_state.sha512);
|
||||
md_final_raw = tls1_sha512_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const uint8_t *block))SHA512_Transform;
|
||||
md_size = 384 / 8;
|
||||
md_transform = tls1_sha512_transform;
|
||||
md_size = SHA384_DIGEST_LENGTH;
|
||||
md_block_size = 128;
|
||||
md_length_size = 16;
|
||||
break;
|
||||
@@ -328,7 +322,7 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
|
||||
assert(md_size <= EVP_MAX_MD_SIZE);
|
||||
|
||||
static const unsigned kHeaderLength = 13;
|
||||
static const size_t kHeaderLength = 13;
|
||||
|
||||
/* kVarianceBlocks is the number of blocks of the hash that we have to
|
||||
* calculate in constant time because they could be altered by the
|
||||
@@ -337,16 +331,16 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
* TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
|
||||
* required to be minimal. Therefore we say that the final six blocks
|
||||
* can vary based on the padding. */
|
||||
static const unsigned kVarianceBlocks = 6;
|
||||
static const size_t kVarianceBlocks = 6;
|
||||
|
||||
/* From now on we're dealing with the MAC, which conceptually has 13
|
||||
* bytes of `header' before the start of the data. */
|
||||
len = data_plus_mac_plus_padding_size + kHeaderLength;
|
||||
size_t len = data_plus_mac_plus_padding_size + kHeaderLength;
|
||||
/* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
|
||||
* |header|, assuming that there's no padding. */
|
||||
max_mac_bytes = len - md_size - 1;
|
||||
* |header|, assuming that there's no padding. */
|
||||
size_t max_mac_bytes = len - md_size - 1;
|
||||
/* num_blocks is the maximum number of hash blocks. */
|
||||
num_blocks =
|
||||
size_t num_blocks =
|
||||
(max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
|
||||
/* In order to calculate the MAC in constant time we have to handle
|
||||
* the final blocks specially because the padding value could cause the
|
||||
@@ -354,43 +348,47 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
* can't leak where. However, |num_starting_blocks| worth of data can
|
||||
* be hashed right away because no padding value can affect whether
|
||||
* they are plaintext. */
|
||||
num_starting_blocks = 0;
|
||||
size_t num_starting_blocks = 0;
|
||||
/* k is the starting byte offset into the conceptual header||data where
|
||||
* we start processing. */
|
||||
k = 0;
|
||||
size_t k = 0;
|
||||
/* mac_end_offset is the index just past the end of the data to be
|
||||
* MACed. */
|
||||
mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
|
||||
size_t mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
|
||||
/* c is the index of the 0x80 byte in the final hash block that
|
||||
* contains application data. */
|
||||
c = mac_end_offset % md_block_size;
|
||||
size_t c = mac_end_offset % md_block_size;
|
||||
/* index_a is the hash block number that contains the 0x80 terminating
|
||||
* value. */
|
||||
index_a = mac_end_offset / md_block_size;
|
||||
size_t index_a = mac_end_offset / md_block_size;
|
||||
/* index_b is the hash block number that contains the 64-bit hash
|
||||
* length, in bits. */
|
||||
index_b = (mac_end_offset + md_length_size) / md_block_size;
|
||||
/* bits is the hash-length in bits. It includes the additional hash
|
||||
* block for the masked HMAC key. */
|
||||
size_t index_b = (mac_end_offset + md_length_size) / md_block_size;
|
||||
|
||||
if (num_blocks > kVarianceBlocks) {
|
||||
num_starting_blocks = num_blocks - kVarianceBlocks;
|
||||
k = md_block_size * num_starting_blocks;
|
||||
}
|
||||
|
||||
bits = 8 * mac_end_offset;
|
||||
/* bits is the hash-length in bits. It includes the additional hash
|
||||
* block for the masked HMAC key. */
|
||||
size_t bits = 8 * mac_end_offset; /* at most 18 bits to represent */
|
||||
|
||||
/* Compute the initial HMAC block. */
|
||||
bits += 8 * md_block_size;
|
||||
/* hmac_pad is the masked HMAC key. */
|
||||
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
|
||||
OPENSSL_memset(hmac_pad, 0, md_block_size);
|
||||
assert(mac_secret_length <= sizeof(hmac_pad));
|
||||
OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length);
|
||||
for (i = 0; i < md_block_size; i++) {
|
||||
for (size_t i = 0; i < md_block_size; i++) {
|
||||
hmac_pad[i] ^= 0x36;
|
||||
}
|
||||
|
||||
md_transform(md_state.c, hmac_pad);
|
||||
md_transform(&md_state, hmac_pad);
|
||||
|
||||
/* The length check means |bits| fits in four bytes. */
|
||||
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
|
||||
OPENSSL_memset(length_bytes, 0, md_length_size - 4);
|
||||
length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
|
||||
length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
|
||||
@@ -399,27 +397,29 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
|
||||
if (k > 0) {
|
||||
/* k is a multiple of md_block_size. */
|
||||
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
|
||||
OPENSSL_memcpy(first_block, header, 13);
|
||||
OPENSSL_memcpy(first_block + 13, data, md_block_size - 13);
|
||||
md_transform(md_state.c, first_block);
|
||||
for (i = 1; i < k / md_block_size; i++) {
|
||||
md_transform(md_state.c, data + md_block_size * i - 13);
|
||||
md_transform(&md_state, first_block);
|
||||
for (size_t i = 1; i < k / md_block_size; i++) {
|
||||
md_transform(&md_state, data + md_block_size * i - 13);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mac_out[EVP_MAX_MD_SIZE];
|
||||
OPENSSL_memset(mac_out, 0, sizeof(mac_out));
|
||||
|
||||
/* We now process the final hash blocks. For each block, we construct
|
||||
* it in constant time. If the |i==index_a| then we'll include the 0x80
|
||||
* bytes and zero pad etc. For each block we selectively copy it, in
|
||||
* constant time, to |mac_out|. */
|
||||
for (i = num_starting_blocks; i <= num_starting_blocks + kVarianceBlocks;
|
||||
i++) {
|
||||
for (size_t i = num_starting_blocks;
|
||||
i <= num_starting_blocks + kVarianceBlocks; i++) {
|
||||
uint8_t block[MAX_HASH_BLOCK_SIZE];
|
||||
uint8_t is_block_a = constant_time_eq_8(i, index_a);
|
||||
uint8_t is_block_b = constant_time_eq_8(i, index_b);
|
||||
for (j = 0; j < md_block_size; j++) {
|
||||
uint8_t b = 0, is_past_c, is_past_cp1;
|
||||
for (size_t j = 0; j < md_block_size; j++) {
|
||||
uint8_t b = 0;
|
||||
if (k < kHeaderLength) {
|
||||
b = header[k];
|
||||
} else if (k < data_plus_mac_plus_padding_size + kHeaderLength) {
|
||||
@@ -427,8 +427,8 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
}
|
||||
k++;
|
||||
|
||||
is_past_c = is_block_a & constant_time_ge_8(j, c);
|
||||
is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
|
||||
uint8_t is_past_c = is_block_a & constant_time_ge_8(j, c);
|
||||
uint8_t is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
|
||||
/* If this is the block containing the end of the
|
||||
* application data, and we are at the offset for the
|
||||
* 0x80 value, then overwrite b with 0x80. */
|
||||
@@ -453,14 +453,15 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
block[j] = b;
|
||||
}
|
||||
|
||||
md_transform(md_state.c, block);
|
||||
md_final_raw(md_state.c, block);
|
||||
md_transform(&md_state, block);
|
||||
md_final_raw(&md_state, block);
|
||||
/* If this is index_b, copy the hash value to |mac_out|. */
|
||||
for (j = 0; j < md_size; j++) {
|
||||
for (size_t j = 0; j < md_size; j++) {
|
||||
mac_out[j] |= block[j] & is_block_b;
|
||||
}
|
||||
}
|
||||
|
||||
EVP_MD_CTX md_ctx;
|
||||
EVP_MD_CTX_init(&md_ctx);
|
||||
if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) {
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
@@ -468,12 +469,13 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
}
|
||||
|
||||
/* Complete the HMAC in the standard manner. */
|
||||
for (i = 0; i < md_block_size; i++) {
|
||||
for (size_t i = 0; i < md_block_size; i++) {
|
||||
hmac_pad[i] ^= 0x6a;
|
||||
}
|
||||
|
||||
EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
|
||||
EVP_DigestUpdate(&md_ctx, mac_out, md_size);
|
||||
unsigned md_out_size_u;
|
||||
EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
|
||||
*md_out_size = md_out_size_u;
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
|
||||
+13
-1
@@ -69,6 +69,10 @@
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* The maximum length we can grow a value to after variable expansion. 64k
|
||||
* should be more than enough for all reasonable uses. */
|
||||
#define MAX_CONF_VALUE_LENGTH 65536
|
||||
|
||||
static uint32_t conf_value_hash(const CONF_VALUE *v) {
|
||||
return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name);
|
||||
}
|
||||
@@ -316,7 +320,15 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from) {
|
||||
OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_HAS_NO_VALUE);
|
||||
goto err;
|
||||
}
|
||||
BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from)));
|
||||
size_t newsize = strlen(p) + buf->length - (e - from);
|
||||
if (newsize > MAX_CONF_VALUE_LENGTH) {
|
||||
OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(buf, newsize)) {
|
||||
OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
while (*p) {
|
||||
buf->data[to++] = *(p++);
|
||||
}
|
||||
|
||||
+63
-234
@@ -49,259 +49,88 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
|
||||
static const unsigned int CONSTTIME_FALSE = 0;
|
||||
static const uint8_t CONSTTIME_TRUE_8 = 0xff;
|
||||
static const uint8_t CONSTTIME_FALSE_8 = 0;
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
|
||||
const char* op_name, unsigned int a, unsigned int b,
|
||||
int is_true) {
|
||||
unsigned c = op(a, b);
|
||||
if (is_true && c != CONSTTIME_TRUE) {
|
||||
fprintf(stderr,
|
||||
"Test failed for %s(%du, %du): expected %du (TRUE), got %du\n",
|
||||
op_name, a, b, CONSTTIME_TRUE, c);
|
||||
return 1;
|
||||
} else if (!is_true && c != CONSTTIME_FALSE) {
|
||||
fprintf(stderr,
|
||||
"Test failed for %s(%du, %du): expected %du (FALSE), got %du\n",
|
||||
op_name, a, b, CONSTTIME_FALSE, c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
static uint8_t FromBool8(bool b) {
|
||||
return b ? CONSTTIME_TRUE_8 : CONSTTIME_FALSE_8;
|
||||
}
|
||||
|
||||
static int test_binary_op_8(uint8_t (*op)(unsigned int a, unsigned int b),
|
||||
const char* op_name, unsigned int a, unsigned int b,
|
||||
int is_true) {
|
||||
uint8_t c = op(a, b);
|
||||
if (is_true && c != CONSTTIME_TRUE_8) {
|
||||
fprintf(stderr,
|
||||
"Test failed for %s(%du, %du): expected %u (TRUE), got %u\n",
|
||||
op_name, a, b, CONSTTIME_TRUE_8, c);
|
||||
return 1;
|
||||
} else if (!is_true && c != CONSTTIME_FALSE_8) {
|
||||
fprintf(stderr,
|
||||
"Test failed for %s(%du, %du): expected %u (FALSE), got %u\n",
|
||||
op_name, a, b, CONSTTIME_FALSE_8, c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
static size_t FromBoolS(bool b) {
|
||||
return b ? CONSTTIME_TRUE_S : CONSTTIME_FALSE_S;
|
||||
}
|
||||
|
||||
static int test_is_zero(unsigned int a) {
|
||||
unsigned int c = constant_time_is_zero(a);
|
||||
if (a == 0 && c != CONSTTIME_TRUE) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_is_zero(%du): expected %du (TRUE), "
|
||||
"got %du\n",
|
||||
a, CONSTTIME_TRUE, c);
|
||||
return 1;
|
||||
} else if (a != 0 && c != CONSTTIME_FALSE) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_is_zero(%du): expected %du (FALSE), "
|
||||
"got %du\n",
|
||||
a, CONSTTIME_FALSE, c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static const uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
|
||||
|
||||
static int test_is_zero_8(unsigned int a) {
|
||||
uint8_t c = constant_time_is_zero_8(a);
|
||||
if (a == 0 && c != CONSTTIME_TRUE_8) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_is_zero(%du): expected %u (TRUE), "
|
||||
"got %u\n",
|
||||
a, CONSTTIME_TRUE_8, c);
|
||||
return 1;
|
||||
} else if (a != 0 && c != CONSTTIME_FALSE) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_is_zero(%du): expected %u (FALSE), "
|
||||
"got %u\n",
|
||||
a, CONSTTIME_FALSE_8, c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_select(unsigned int a, unsigned int b) {
|
||||
unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
|
||||
if (selected != a) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_select(%du, %du,"
|
||||
"%du): expected %du(first value), got %du\n",
|
||||
CONSTTIME_TRUE, a, b, a, selected);
|
||||
return 1;
|
||||
}
|
||||
selected = constant_time_select(CONSTTIME_FALSE, a, b);
|
||||
if (selected != b) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_select(%du, %du,"
|
||||
"%du): expected %du(second value), got %du\n",
|
||||
CONSTTIME_FALSE, a, b, b, selected);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_select_8(uint8_t a, uint8_t b) {
|
||||
uint8_t selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
|
||||
if (selected != a) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_select(%u, %u,"
|
||||
"%u): expected %u(first value), got %u\n",
|
||||
CONSTTIME_TRUE, a, b, a, selected);
|
||||
return 1;
|
||||
}
|
||||
selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
|
||||
if (selected != b) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_select(%u, %u,"
|
||||
"%u): expected %u(second value), got %u\n",
|
||||
CONSTTIME_FALSE, a, b, b, selected);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_select_int(int a, int b) {
|
||||
int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
|
||||
if (selected != a) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_select(%du, %d,"
|
||||
"%d): expected %d(first value), got %d\n",
|
||||
CONSTTIME_TRUE, a, b, a, selected);
|
||||
return 1;
|
||||
}
|
||||
selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
|
||||
if (selected != b) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_select(%du, %d,"
|
||||
"%d): expected %d(second value), got %d\n",
|
||||
CONSTTIME_FALSE, a, b, b, selected);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_eq_int(int a, int b) {
|
||||
unsigned int equal = constant_time_eq_int(a, b);
|
||||
if (a == b && equal != CONSTTIME_TRUE) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_eq_int(%d, %d): expected %du(TRUE), "
|
||||
"got %du\n",
|
||||
a, b, CONSTTIME_TRUE, equal);
|
||||
return 1;
|
||||
} else if (a != b && equal != CONSTTIME_FALSE) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_eq_int(%d, %d): expected "
|
||||
"%du(FALSE), got %du\n",
|
||||
a, b, CONSTTIME_FALSE, equal);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_eq_int_8(int a, int b) {
|
||||
uint8_t equal = constant_time_eq_int_8(a, b);
|
||||
if (a == b && equal != CONSTTIME_TRUE_8) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_eq_int_8(%d, %d): expected "
|
||||
"%u(TRUE), got %u\n",
|
||||
a, b, CONSTTIME_TRUE_8, equal);
|
||||
return 1;
|
||||
} else if (a != b && equal != CONSTTIME_FALSE_8) {
|
||||
fprintf(stderr,
|
||||
"Test failed for constant_time_eq_int_8(%d, %d): expected "
|
||||
"%u(FALSE), got %u\n",
|
||||
a, b, CONSTTIME_FALSE_8, equal);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
|
||||
UINT_MAX / 2, UINT_MAX / 2 + 1,
|
||||
UINT_MAX - 1, UINT_MAX};
|
||||
|
||||
static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
|
||||
static size_t test_values_s[] = {
|
||||
0,
|
||||
1,
|
||||
1024,
|
||||
12345,
|
||||
32000,
|
||||
#if defined(OPENSSL_64_BIT)
|
||||
0xffffffff / 2 - 1,
|
||||
0xffffffff / 2,
|
||||
0xffffffff / 2 + 1,
|
||||
0xffffffff - 1,
|
||||
0xffffffff,
|
||||
#endif
|
||||
std::numeric_limits<size_t>::max() / 2 - 1,
|
||||
std::numeric_limits<size_t>::max() / 2,
|
||||
std::numeric_limits<size_t>::max() / 2 + 1,
|
||||
std::numeric_limits<size_t>::max() - 1,
|
||||
std::numeric_limits<size_t>::max(),
|
||||
};
|
||||
|
||||
static int signed_test_values[] = {
|
||||
0, 1, -1, 1024, -1024, 12345, -12345,
|
||||
32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
unsigned int a, b, i, j;
|
||||
int c, d;
|
||||
uint8_t e, f;
|
||||
int num_failed = 0, num_all = 0;
|
||||
fprintf(stdout, "Testing constant time operations...\n");
|
||||
TEST(ConstantTimeTest, Test) {
|
||||
for (size_t a : test_values_s) {
|
||||
SCOPED_TRACE(a);
|
||||
|
||||
for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) {
|
||||
a = test_values[i];
|
||||
num_failed += test_is_zero(a);
|
||||
num_failed += test_is_zero_8(a);
|
||||
num_all += 2;
|
||||
for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) {
|
||||
b = test_values[j];
|
||||
num_failed +=
|
||||
test_binary_op(&constant_time_lt, "constant_time_lt", a, b, a < b);
|
||||
num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
|
||||
a, b, a < b);
|
||||
num_failed +=
|
||||
test_binary_op(&constant_time_lt, "constant_time_lt_8", b, a, b < a);
|
||||
num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
|
||||
b, a, b < a);
|
||||
num_failed +=
|
||||
test_binary_op(&constant_time_ge, "constant_time_ge", a, b, a >= b);
|
||||
num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
|
||||
a, b, a >= b);
|
||||
num_failed +=
|
||||
test_binary_op(&constant_time_ge, "constant_time_ge", b, a, b >= a);
|
||||
num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
|
||||
b, a, b >= a);
|
||||
num_failed +=
|
||||
test_binary_op(&constant_time_eq, "constant_time_eq", a, b, a == b);
|
||||
num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
|
||||
a, b, a == b);
|
||||
num_failed +=
|
||||
test_binary_op(&constant_time_eq, "constant_time_eq", b, a, b == a);
|
||||
num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
|
||||
b, a, b == a);
|
||||
num_failed += test_select(a, b);
|
||||
num_all += 13;
|
||||
EXPECT_EQ(FromBoolS(a == 0), constant_time_is_zero_s(a));
|
||||
EXPECT_EQ(FromBool8(a == 0), constant_time_is_zero_8(a));
|
||||
|
||||
for (size_t b : test_values_s) {
|
||||
SCOPED_TRACE(b);
|
||||
|
||||
EXPECT_EQ(FromBoolS(a < b), constant_time_lt_s(a, b));
|
||||
EXPECT_EQ(FromBool8(a < b), constant_time_lt_8(a, b));
|
||||
|
||||
EXPECT_EQ(FromBoolS(a >= b), constant_time_ge_s(a, b));
|
||||
EXPECT_EQ(FromBool8(a >= b), constant_time_ge_8(a, b));
|
||||
|
||||
EXPECT_EQ(FromBoolS(a == b), constant_time_eq_s(a, b));
|
||||
EXPECT_EQ(FromBool8(a == b), constant_time_eq_8(a, b));
|
||||
|
||||
EXPECT_EQ(a, constant_time_select_s(CONSTTIME_TRUE_S, a, b));
|
||||
EXPECT_EQ(b, constant_time_select_s(CONSTTIME_FALSE_S, a, b));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) {
|
||||
c = signed_test_values[i];
|
||||
for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) {
|
||||
d = signed_test_values[j];
|
||||
num_failed += test_select_int(c, d);
|
||||
num_failed += test_eq_int(c, d);
|
||||
num_failed += test_eq_int_8(c, d);
|
||||
num_all += 3;
|
||||
for (int a : signed_test_values) {
|
||||
SCOPED_TRACE(a);
|
||||
for (int b : signed_test_values) {
|
||||
SCOPED_TRACE(b);
|
||||
|
||||
EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE_S, a, b));
|
||||
EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE_S, a, b));
|
||||
|
||||
EXPECT_EQ(FromBoolS(a == b), constant_time_eq_int(a, b));
|
||||
EXPECT_EQ(FromBool8(a == b), constant_time_eq_int_8(a, b));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test_values_8); ++i) {
|
||||
e = test_values_8[i];
|
||||
for (j = 0; j < sizeof(test_values_8); ++j) {
|
||||
f = test_values_8[j];
|
||||
num_failed += test_select_8(e, f);
|
||||
num_all += 1;
|
||||
for (uint8_t a : test_values_8) {
|
||||
SCOPED_TRACE(static_cast<int>(a));
|
||||
for (uint8_t b : test_values_8) {
|
||||
SCOPED_TRACE(static_cast<int>(b));
|
||||
EXPECT_EQ(a, constant_time_select_8(CONSTTIME_TRUE_8, a, b));
|
||||
EXPECT_EQ(b, constant_time_select_8(CONSTTIME_FALSE_8, a, b));
|
||||
}
|
||||
}
|
||||
|
||||
if (!num_failed) {
|
||||
fprintf(stdout, "ok (ran %d tests)\n", num_all);
|
||||
fprintf(stdout, "PASS\n");
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,12 @@
|
||||
#define PPC_FEATURE2_HAS_VCRYPTO 0x02000000
|
||||
#endif
|
||||
|
||||
static unsigned long g_ppc64le_hwcap2 = 0;
|
||||
|
||||
void OPENSSL_cpuid_setup(void) {
|
||||
g_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
|
||||
OPENSSL_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
|
||||
}
|
||||
|
||||
int CRYPTO_is_PPC64LE_vcrypto_capable(void) {
|
||||
return (g_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
|
||||
return (OPENSSL_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_PPC64LE */
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
* far, the init constructor function only sets the capability variables. */
|
||||
|
||||
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
|
||||
|
||||
/* This value must be explicitly initialised to zero in order to work around a
|
||||
* bug in libtool or the linker on OS X.
|
||||
*
|
||||
@@ -57,6 +58,11 @@
|
||||
* initialising it to zero, it becomes a "data symbol", which isn't so
|
||||
* affected. */
|
||||
uint32_t OPENSSL_ia32cap_P[4] = {0};
|
||||
|
||||
#elif defined(OPENSSL_PPC64LE)
|
||||
|
||||
unsigned long OPENSSL_ppc64le_hwcap2 = 0;
|
||||
|
||||
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
|
||||
|
||||
#include <openssl/arm_arch.h>
|
||||
|
||||
@@ -38,15 +38,6 @@ add_executable(
|
||||
target_link_libraries(ed25519_test crypto)
|
||||
add_dependencies(all_tests ed25519_test)
|
||||
|
||||
add_executable(
|
||||
x25519_test
|
||||
|
||||
x25519_test.cc
|
||||
)
|
||||
|
||||
target_link_libraries(x25519_test crypto)
|
||||
add_dependencies(all_tests x25519_test)
|
||||
|
||||
add_executable(
|
||||
spake25519_test
|
||||
|
||||
|
||||
@@ -2575,3 +2575,16 @@ PRIV: 4f4b20d899366f2f23ee628f229b236cf80f43ba183177c97ee34829546f1742c94576641f
|
||||
PUB: c94576641f4a893cdfcee7b39fc21929b86b349976d7b0a46d39a588bcfe4357
|
||||
MESSAGE: db8ef02e3033e6b96a56cab05082fb4695f4a1c916250dd75173f430a10c9468817709d37623346ae8245b42bda0da6b60462ccfdfc75a9ab994e66c9ab9fecdd8599610910affe4f10215cb280bf8f9f2700a444796dae93e06c6bea7d8b4fe1301baa79ccec769368feb2442c7de84f095e6b3bff63d388cbafb2b9809dc38e9b12ebd039c0a57f4d522e91ec8d1f2b8d23a4a0ae059af85393bb0a15f749110f6774a1fd731a6ec213e4ff435daab546d31ed9ec3b6d8cc2edacebf4facc5566556eea92e5b3f2542239b25e28012dd4ef40072eebf83ed2a255181f3a442189d68c6c609f4dfdf3db7d67d087a2fcd6d2dc50bbfed8bfbbfcb74d3c41f02a87865b13b8efcf5c3581257be0aa913f60c370527bde11a475c136a17c5eefeb03f5bff28693ed841e8ed1f7c29102f5599dd444009bcea6a92d5574152458e0caf8a36aa72b5dc4908a6461c9b741453005c8fbcc68113ae184208ee14b835480c6efafed18a76000b38e5858290f4d51f52f096cbe490e1eb5cacb226ec495a55a7fa457843d57fab67f8be7e209334785bdd665d7b63e4daf57b6e78928b603c8c0f9bc85464733b61273ef9e2b8a0cd7c3bf8ee0a6872e34d5a27a625e35eaf7ff5440b8b141af704df70c9c18623bd11209513192505105cd7bcfa5f0d919da706948fbe1f761f315846aa3b4813dd9ba3d81b9204e5409c0382b6eb
|
||||
SIG: 0f80ff5d17488fe26f93c543b04ed959b5f0643fc61c7f2c3bc60132ba9c6210c8b250ea5e84d07b01de68bc174414eeeb31fdc2ba6823e231e312a91ededd02
|
||||
|
||||
|
||||
# Additional test vectors from RFC 8032
|
||||
|
||||
PRIV: f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
|
||||
PUB: 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
|
||||
MESSAGE: 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0
|
||||
SIG: 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03
|
||||
|
||||
PRIV: 833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
|
||||
PUB: ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
|
||||
MESSAGE: ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
|
||||
SIG: dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/curve25519.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
static bool TestX25519() {
|
||||
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
|
||||
TEST(X25519Test, TestVector) {
|
||||
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2
|
||||
static const uint8_t kScalar1[32] = {
|
||||
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
|
||||
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
|
||||
@@ -35,17 +38,14 @@ static bool TestX25519() {
|
||||
};
|
||||
|
||||
uint8_t out[32];
|
||||
X25519(out, kScalar1, kPoint1);
|
||||
EXPECT_TRUE(X25519(out, kScalar1, kPoint1));
|
||||
|
||||
static const uint8_t kExpected1[32] = {
|
||||
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
|
||||
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
|
||||
0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
|
||||
};
|
||||
if (OPENSSL_memcmp(kExpected1, out, sizeof(out)) != 0) {
|
||||
fprintf(stderr, "X25519 test one failed.\n");
|
||||
return false;
|
||||
}
|
||||
EXPECT_EQ(Bytes(kExpected1), Bytes(out));
|
||||
|
||||
static const uint8_t kScalar2[32] = {
|
||||
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26,
|
||||
@@ -58,22 +58,17 @@ static bool TestX25519() {
|
||||
0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
|
||||
};
|
||||
|
||||
X25519(out, kScalar2, kPoint2);
|
||||
EXPECT_TRUE(X25519(out, kScalar2, kPoint2));
|
||||
|
||||
static const uint8_t kExpected2[32] = {
|
||||
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
|
||||
0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
|
||||
0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
|
||||
};
|
||||
if (OPENSSL_memcmp(kExpected2, out, sizeof(out)) != 0) {
|
||||
fprintf(stderr, "X25519 test two failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
EXPECT_EQ(Bytes(kExpected2), Bytes(out));
|
||||
}
|
||||
|
||||
static bool TestX25519SmallOrder() {
|
||||
TEST(X25519Test, SmallOrder) {
|
||||
static const uint8_t kSmallOrderPoint[32] = {
|
||||
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
|
||||
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
|
||||
@@ -83,21 +78,21 @@ static bool TestX25519SmallOrder() {
|
||||
uint8_t out[32], private_key[32];
|
||||
OPENSSL_memset(private_key, 0x11, sizeof(private_key));
|
||||
|
||||
if (X25519(out, private_key, kSmallOrderPoint)) {
|
||||
fprintf(stderr, "X25519 returned success with a small-order input.\n");
|
||||
return false;
|
||||
}
|
||||
OPENSSL_memset(out, 0xff, sizeof(out));
|
||||
EXPECT_FALSE(X25519(out, private_key, kSmallOrderPoint))
|
||||
<< "X25519 returned success with a small-order input.";
|
||||
|
||||
return true;
|
||||
// For callers which don't check, |out| should still be filled with zeros.
|
||||
static const uint8_t kZeros[32] = {0};
|
||||
EXPECT_EQ(Bytes(kZeros), Bytes(out));
|
||||
}
|
||||
|
||||
static bool TestX25519Iterated() {
|
||||
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
|
||||
TEST(X25519Test, Iterated) {
|
||||
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2.
|
||||
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < 1000; i++) {
|
||||
X25519(out, scalar, point);
|
||||
for (unsigned i = 0; i < 1000; i++) {
|
||||
EXPECT_TRUE(X25519(out, scalar, point));
|
||||
OPENSSL_memcpy(point, scalar, sizeof(point));
|
||||
OPENSSL_memcpy(scalar, out, sizeof(scalar));
|
||||
}
|
||||
@@ -108,21 +103,5 @@ static bool TestX25519Iterated() {
|
||||
0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
|
||||
};
|
||||
|
||||
if (OPENSSL_memcmp(kExpected, scalar, sizeof(kExpected)) != 0) {
|
||||
fprintf(stderr, "Iterated X25519 test failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (!TestX25519() ||
|
||||
!TestX25519Iterated() ||
|
||||
!TestX25519SmallOrder()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
EXPECT_EQ(Bytes(kExpected), Bytes(scalar));
|
||||
}
|
||||
|
||||
+2
-2
@@ -93,7 +93,7 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
|
||||
/* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114
|
||||
* groups which are not safe primes but pick a generator on a prime-order
|
||||
* subgroup of size |dh->q|. */
|
||||
if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) {
|
||||
if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
if (!BN_is_one(tmp)) {
|
||||
@@ -145,7 +145,7 @@ int DH_check(const DH *dh, int *ret) {
|
||||
*ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
|
||||
} else {
|
||||
/* Check g^q == 1 mod p */
|
||||
if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) {
|
||||
if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
if (!BN_is_one(t1)) {
|
||||
|
||||
@@ -225,13 +225,6 @@ static int TestDigest(const TestVector *test) {
|
||||
if (!CompareDigest(test, digest.get(), EVP_MD_size(test->md.func()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test the deprecated static buffer variant, until it's removed.
|
||||
out = test->md.one_shot_func((const uint8_t *)test->input,
|
||||
strlen(test->input), NULL);
|
||||
if (!CompareDigest(test, out, EVP_MD_size(test->md.func()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+44
-5
@@ -60,6 +60,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/md4.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/nid.h>
|
||||
@@ -328,20 +329,58 @@ static const struct {
|
||||
{ {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, EVP_sha224 },
|
||||
};
|
||||
|
||||
static const EVP_MD *cbs_to_md(const CBS *cbs) {
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
|
||||
if (CBS_len(cbs) == kMDOIDs[i].oid_len &&
|
||||
OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) ==
|
||||
0) {
|
||||
return kMDOIDs[i].md_func();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj) {
|
||||
/* Handle objects with no corresponding OID. */
|
||||
if (obj->nid != NID_undef) {
|
||||
return EVP_get_digestbynid(obj->nid);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
|
||||
if (obj->length == kMDOIDs[i].oid_len &&
|
||||
memcmp(obj->data, kMDOIDs[i].oid, obj->length) == 0) {
|
||||
return kMDOIDs[i].md_func();
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, obj->data, obj->length);
|
||||
return cbs_to_md(&cbs);
|
||||
}
|
||||
|
||||
const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) {
|
||||
CBS algorithm, oid;
|
||||
if (!CBS_get_asn1(cbs, &algorithm, CBS_ASN1_SEQUENCE) ||
|
||||
!CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) {
|
||||
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const EVP_MD *ret = cbs_to_md(&oid);
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The parameters, if present, must be NULL. Historically, whether the NULL
|
||||
* was included or omitted was not well-specified. When parsing an
|
||||
* AlgorithmIdentifier, we allow both. (Note this code is not used when
|
||||
* verifying RSASSA-PKCS1-v1_5 signatures.) */
|
||||
if (CBS_len(&algorithm) > 0) {
|
||||
CBS param;
|
||||
if (!CBS_get_asn1(&algorithm, ¶m, CBS_ASN1_NULL) ||
|
||||
CBS_len(¶m) != 0 ||
|
||||
CBS_len(&algorithm) != 0) {
|
||||
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const EVP_MD *EVP_get_digestbyname(const char *name) {
|
||||
|
||||
@@ -104,6 +104,8 @@ struct evp_md_pctx_ops {
|
||||
EVP_PKEY_CTX* (*dup) (EVP_PKEY_CTX *pctx);
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
|
||||
@@ -3,4 +3,5 @@ CONF,101,MISSING_CLOSE_SQUARE_BRACKET
|
||||
CONF,102,MISSING_EQUAL_SIGN
|
||||
CONF,103,NO_CLOSE_BRACE
|
||||
CONF,104,UNABLE_TO_CREATE_NEW_SECTION
|
||||
CONF,106,VARIABLE_EXPANSION_TOO_LONG
|
||||
CONF,105,VARIABLE_HAS_NO_VALUE
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
DIGEST,101,DECODE_ERROR
|
||||
DIGEST,100,INPUT_NOT_INITIALIZED
|
||||
DIGEST,102,UNKNOWN_HASH
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
PKCS8,129,BAD_ITERATION_COUNT
|
||||
PKCS8,100,BAD_PKCS12_DATA
|
||||
PKCS8,101,BAD_PKCS12_VERSION
|
||||
PKCS8,102,CIPHER_HAS_NO_OBJECT_IDENTIFIER
|
||||
@@ -22,4 +23,9 @@ PKCS8,120,UNKNOWN_CIPHER
|
||||
PKCS8,121,UNKNOWN_CIPHER_ALGORITHM
|
||||
PKCS8,122,UNKNOWN_DIGEST
|
||||
PKCS8,123,UNKNOWN_HASH
|
||||
PKCS8,127,UNSUPPORTED_CIPHER
|
||||
PKCS8,125,UNSUPPORTED_KEYLENGTH
|
||||
PKCS8,128,UNSUPPORTED_KEY_DERIVATION_FUNCTION
|
||||
PKCS8,130,UNSUPPORTED_PRF
|
||||
PKCS8,124,UNSUPPORTED_PRIVATE_KEY_ALGORITHM
|
||||
PKCS8,126,UNSUPPORTED_SALT_TYPE
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
SSL,277,ALPN_MISMATCH_ON_EARLY_DATA
|
||||
SSL,100,APP_DATA_IN_HANDSHAKE
|
||||
SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT
|
||||
SSL,102,BAD_ALERT
|
||||
@@ -22,14 +23,17 @@ SSL,261,BLOCK_CIPHER_PAD_IS_WRONG
|
||||
SSL,120,BN_LIB
|
||||
SSL,255,BUFFERED_MESSAGES_ON_CIPHER_CHANGE
|
||||
SSL,121,BUFFER_TOO_SMALL
|
||||
SSL,275,CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD
|
||||
SSL,272,CANNOT_PARSE_LEAF_CERT
|
||||
SSL,122,CA_DN_LENGTH_MISMATCH
|
||||
SSL,123,CA_DN_TOO_LONG
|
||||
SSL,124,CCS_RECEIVED_EARLY
|
||||
SSL,274,CERTIFICATE_AND_PRIVATE_KEY_MISMATCH
|
||||
SSL,125,CERTIFICATE_VERIFY_FAILED
|
||||
SSL,126,CERT_CB_ERROR
|
||||
SSL,127,CERT_LENGTH_MISMATCH
|
||||
SSL,128,CHANNEL_ID_NOT_P256
|
||||
SSL,279,CHANNEL_ID_ON_EARLY_DATA
|
||||
SSL,129,CHANNEL_ID_SIGNATURE_INVALID
|
||||
SSL,130,CIPHER_OR_HASH_UNAVAILABLE
|
||||
SSL,131,CLIENTHELLO_PARSE_FAILED
|
||||
@@ -71,7 +75,6 @@ SSL,269,INVALID_SCT_LIST
|
||||
SSL,160,INVALID_SSL_SESSION
|
||||
SSL,161,INVALID_TICKET_KEYS_LENGTH
|
||||
SSL,162,LENGTH_MISMATCH
|
||||
SSL,163,LIBRARY_HAS_NO_CIPHERS
|
||||
SSL,164,MISSING_EXTENSION
|
||||
SSL,258,MISSING_KEY_SHARE
|
||||
SSL,165,MISSING_RSA_CERTIFICATE
|
||||
@@ -125,6 +128,7 @@ SSL,204,RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION
|
||||
SSL,205,RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION
|
||||
SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING
|
||||
SSL,207,SERVERHELLO_TLSEXT
|
||||
SSL,273,SERVER_CERT_CHANGED
|
||||
SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED
|
||||
SSL,209,SESSION_MAY_NOT_BE_CREATED
|
||||
SSL,250,SHUTDOWN_WHILE_IN_INIT
|
||||
@@ -147,6 +151,7 @@ SSL,1043,SSLV3_ALERT_UNSUPPORTED_CERTIFICATE
|
||||
SSL,214,SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION
|
||||
SSL,215,SSL_HANDSHAKE_FAILURE
|
||||
SSL,216,SSL_SESSION_ID_CONTEXT_TOO_LONG
|
||||
SSL,276,TICKET_ENCRYPTION_FAILED
|
||||
SSL,1049,TLSV1_ALERT_ACCESS_DENIED
|
||||
SSL,1050,TLSV1_ALERT_DECODE_ERROR
|
||||
SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED
|
||||
@@ -201,5 +206,6 @@ SSL,244,WRONG_MESSAGE_TYPE
|
||||
SSL,245,WRONG_SIGNATURE_TYPE
|
||||
SSL,246,WRONG_SSL_VERSION
|
||||
SSL,247,WRONG_VERSION_NUMBER
|
||||
SSL,278,WRONG_VERSION_ON_EARLY_DATA
|
||||
SSL,248,X509_LIB
|
||||
SSL,249,X509_VERIFICATION_SETUP_PROBLEMS
|
||||
|
||||
@@ -20,14 +20,6 @@ add_library(
|
||||
)
|
||||
|
||||
|
||||
add_executable(
|
||||
evp_extra_test
|
||||
|
||||
evp_extra_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
add_executable(
|
||||
evp_test
|
||||
|
||||
@@ -44,7 +36,6 @@ add_executable(
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(evp_extra_test crypto)
|
||||
target_link_libraries(evp_test crypto)
|
||||
target_link_libraries(pbkdf_test crypto)
|
||||
add_dependencies(all_tests evp_extra_test evp_test pbkdf_test)
|
||||
add_dependencies(all_tests evp_test pbkdf_test)
|
||||
|
||||
@@ -120,13 +120,6 @@ int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
|
||||
if (pkey->ameth && pkey->ameth->pkey_supports_digest) {
|
||||
return pkey->ameth->pkey_supports_digest(pkey, md);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
|
||||
if (a->type != b->type) {
|
||||
return -1;
|
||||
|
||||
+101
-280
@@ -20,6 +20,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/digest.h>
|
||||
@@ -28,6 +30,7 @@
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
// kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
|
||||
@@ -370,352 +373,170 @@ static bssl::UniquePtr<EVP_PKEY> LoadExampleRSAKey() {
|
||||
return pkey;
|
||||
}
|
||||
|
||||
static bool TestEVP_DigestSignInit(void) {
|
||||
TEST(EVPExtraTest, DigestSignInit) {
|
||||
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
|
||||
ASSERT_TRUE(pkey);
|
||||
bssl::ScopedEVP_MD_CTX md_ctx;
|
||||
if (!pkey ||
|
||||
!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
|
||||
!EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(
|
||||
EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
|
||||
ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
|
||||
|
||||
// Determine the size of the signature.
|
||||
size_t sig_len = 0;
|
||||
if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len));
|
||||
|
||||
// Sanity check for testing.
|
||||
if (sig_len != (size_t)EVP_PKEY_size(pkey.get())) {
|
||||
fprintf(stderr, "sig_len mismatch\n");
|
||||
return false;
|
||||
}
|
||||
EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(pkey.get())), sig_len);
|
||||
|
||||
std::vector<uint8_t> sig;
|
||||
sig.resize(sig_len);
|
||||
if (!EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len)) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len));
|
||||
sig.resize(sig_len);
|
||||
|
||||
// Ensure that the signature round-trips.
|
||||
md_ctx.Reset();
|
||||
if (!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
|
||||
pkey.get()) ||
|
||||
!EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
|
||||
!EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
ASSERT_TRUE(
|
||||
EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
|
||||
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
|
||||
ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len));
|
||||
}
|
||||
|
||||
static bool TestEVP_DigestVerifyInit(void) {
|
||||
TEST(EVPExtraTest, DigestVerifyInit) {
|
||||
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
|
||||
bssl::ScopedEVP_MD_CTX md_ctx;
|
||||
if (!pkey ||
|
||||
!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
|
||||
pkey.get()) ||
|
||||
!EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
|
||||
!EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
ASSERT_TRUE(pkey);
|
||||
ASSERT_TRUE(
|
||||
EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
|
||||
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
|
||||
ASSERT_TRUE(
|
||||
EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature)));
|
||||
}
|
||||
|
||||
static bool TestVerifyRecover() {
|
||||
TEST(EVPExtraTest, VerifyRecover) {
|
||||
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
|
||||
if (!pkey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(pkey);
|
||||
bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey.get()));
|
||||
if (!rsa) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(rsa);
|
||||
|
||||
const uint8_t kDummyHash[32] = {0};
|
||||
uint8_t sig[2048/8];
|
||||
unsigned sig_len = sizeof(sig);
|
||||
|
||||
if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig, &sig_len,
|
||||
rsa.get())) {
|
||||
fprintf(stderr, "RSA_sign failed.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig,
|
||||
&sig_len, rsa.get()));
|
||||
|
||||
size_t out_len;
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
|
||||
if (!EVP_PKEY_verify_recover_init(ctx.get()) ||
|
||||
!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) ||
|
||||
!EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()) ||
|
||||
!EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len)) {
|
||||
fprintf(stderr, "verify_recover failed will nullptr buffer.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_PKEY_verify_recover_init(ctx.get()));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()));
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len));
|
||||
|
||||
std::vector<uint8_t> recovered;
|
||||
recovered.resize(out_len);
|
||||
|
||||
if (!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
|
||||
sig_len)) {
|
||||
fprintf(stderr, "verify_recover failed.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_len != sizeof(kDummyHash)) {
|
||||
fprintf(stderr, "verify_recover length is %u, expected %u.\n",
|
||||
static_cast<unsigned>(out_len),
|
||||
static_cast<unsigned>(sizeof(kDummyHash)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OPENSSL_memcmp(recovered.data(), kDummyHash, sizeof(kDummyHash)) != 0) {
|
||||
fprintf(stderr, "verify_recover got wrong value.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
|
||||
sig, sig_len));
|
||||
EXPECT_EQ(Bytes(kDummyHash), Bytes(recovered.data(), out_len));
|
||||
|
||||
out_len = recovered.size();
|
||||
if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr) ||
|
||||
!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
|
||||
sig_len)) {
|
||||
fprintf(stderr, "verify_recover failed with NULL MD.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr));
|
||||
ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
|
||||
sig, sig_len));
|
||||
|
||||
/* The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
|
||||
* bytes. */
|
||||
static const size_t kExpectedASN1Size = 51;
|
||||
if (out_len != kExpectedASN1Size) {
|
||||
fprintf(stderr, "verify_recover length without MD is %u, expected %u.\n",
|
||||
static_cast<unsigned>(out_len),
|
||||
static_cast<unsigned>(kExpectedASN1Size));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
|
||||
// bytes.
|
||||
EXPECT_EQ(51u, out_len);
|
||||
}
|
||||
|
||||
static bool TestValidPrivateKey(const uint8_t *input, size_t input_len,
|
||||
static void TestValidPrivateKey(const uint8_t *input, size_t input_len,
|
||||
int expected_id) {
|
||||
const uint8_t *p = input;
|
||||
bssl::UniquePtr<EVP_PKEY> pkey(d2i_AutoPrivateKey(NULL, &p, input_len));
|
||||
if (!pkey || p != input + input_len) {
|
||||
fprintf(stderr, "d2i_AutoPrivateKey failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_id(pkey.get()) != expected_id) {
|
||||
fprintf(stderr, "Did not decode expected type\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
ASSERT_TRUE(pkey);
|
||||
EXPECT_EQ(input + input_len, p);
|
||||
EXPECT_EQ(expected_id, EVP_PKEY_id(pkey.get()));
|
||||
}
|
||||
|
||||
static bool Testd2i_AutoPrivateKey() {
|
||||
if (!TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
|
||||
EVP_PKEY_RSA)) {
|
||||
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
|
||||
EVP_PKEY_RSA)) {
|
||||
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
|
||||
EVP_PKEY_EC)) {
|
||||
fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
|
||||
EVP_PKEY_EC)) {
|
||||
fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyPKCS8) failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
|
||||
sizeof(kExampleECKeySpecifiedCurvePKCS8),
|
||||
EVP_PKEY_EC)) {
|
||||
fprintf(stderr,
|
||||
"d2i_AutoPrivateKey(kExampleECKeySpecifiedCurvePKCS8) failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
|
||||
EVP_PKEY_DSA)) {
|
||||
fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n");
|
||||
return false;
|
||||
}
|
||||
TEST(EVPExtraTest, d2i_AutoPrivateKey) {
|
||||
TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
|
||||
EVP_PKEY_RSA);
|
||||
TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
|
||||
EVP_PKEY_RSA);
|
||||
TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER), EVP_PKEY_EC);
|
||||
TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
|
||||
EVP_PKEY_EC);
|
||||
TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
|
||||
sizeof(kExampleECKeySpecifiedCurvePKCS8), EVP_PKEY_EC);
|
||||
TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
|
||||
EVP_PKEY_DSA);
|
||||
|
||||
const uint8_t *p = kInvalidPrivateKey;
|
||||
bssl::UniquePtr<EVP_PKEY> pkey(d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
|
||||
if (pkey) {
|
||||
fprintf(stderr, "Parsed invalid private key\n");
|
||||
return false;
|
||||
}
|
||||
bssl::UniquePtr<EVP_PKEY> pkey(
|
||||
d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
|
||||
EXPECT_FALSE(pkey) << "Parsed invalid private key";
|
||||
ERR_clear_error();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TestEVP_PKCS82PKEY tests loading a bad key in PKCS8 format.
|
||||
static bool TestEVP_PKCS82PKEY(void) {
|
||||
// Tests loading a bad key in PKCS8 format.
|
||||
TEST(EVPExtraTest, BadECKey) {
|
||||
const uint8_t *derp = kExampleBadECKeyDER;
|
||||
bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> p8inf(
|
||||
d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER)));
|
||||
if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) {
|
||||
fprintf(stderr, "Failed to parse key\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(p8inf);
|
||||
EXPECT_EQ(kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER), derp);
|
||||
|
||||
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKCS82PKEY(p8inf.get()));
|
||||
if (pkey) {
|
||||
fprintf(stderr, "Imported invalid EC key\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_FALSE(pkey) << "Imported invalid EC key";
|
||||
ERR_clear_error();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TestEVPMarshalEmptyPublicKey tests |EVP_marshal_public_key| on an empty key.
|
||||
static bool TestEVPMarshalEmptyPublicKey(void) {
|
||||
// Tests |EVP_marshal_public_key| on an empty key.
|
||||
TEST(EVPExtraTest, MarshalEmptyPublicKey) {
|
||||
bssl::UniquePtr<EVP_PKEY> empty(EVP_PKEY_new());
|
||||
if (!empty) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(empty);
|
||||
|
||||
bssl::ScopedCBB cbb;
|
||||
if (EVP_marshal_public_key(cbb.get(), empty.get())) {
|
||||
fprintf(stderr, "Marshalled empty public key.\n");
|
||||
return false;
|
||||
}
|
||||
if (ERR_GET_REASON(ERR_peek_last_error()) != EVP_R_UNSUPPORTED_ALGORITHM) {
|
||||
fprintf(stderr, "Marshalling an empty public key gave wrong error.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
return true;
|
||||
EXPECT_FALSE(EVP_marshal_public_key(cbb.get(), empty.get()))
|
||||
<< "Marshalled empty public key.";
|
||||
EXPECT_EQ(EVP_R_UNSUPPORTED_ALGORITHM, ERR_GET_REASON(ERR_peek_last_error()));
|
||||
}
|
||||
|
||||
// Testd2i_PrivateKey tests |d2i_PrivateKey|.
|
||||
static bool Testd2i_PrivateKey(void) {
|
||||
const uint8_t *derp = kExampleRSAKeyDER;
|
||||
bssl::UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
|
||||
sizeof(kExampleRSAKeyDER)));
|
||||
if (!pkey || derp != kExampleRSAKeyDER + sizeof(kExampleRSAKeyDER)) {
|
||||
fprintf(stderr, "Failed to import raw RSA key.\n");
|
||||
return false;
|
||||
static bssl::UniquePtr<EVP_PKEY> ParsePrivateKey(int type, const uint8_t *in,
|
||||
size_t len) {
|
||||
const uint8_t *ptr = in;
|
||||
bssl::UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(type, nullptr, &ptr, len));
|
||||
if (!pkey) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
derp = kExampleDSAKeyDER;
|
||||
pkey.reset(d2i_PrivateKey(EVP_PKEY_DSA, nullptr, &derp,
|
||||
sizeof(kExampleDSAKeyDER)));
|
||||
if (!pkey || derp != kExampleDSAKeyDER + sizeof(kExampleDSAKeyDER)) {
|
||||
fprintf(stderr, "Failed to import raw DSA key.\n");
|
||||
return false;
|
||||
}
|
||||
EXPECT_EQ(in + len, ptr);
|
||||
return pkey;
|
||||
}
|
||||
|
||||
derp = kExampleRSAKeyPKCS8;
|
||||
pkey.reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
|
||||
sizeof(kExampleRSAKeyPKCS8)));
|
||||
if (!pkey || derp != kExampleRSAKeyPKCS8 + sizeof(kExampleRSAKeyPKCS8)) {
|
||||
fprintf(stderr, "Failed to import PKCS#8 RSA key.\n");
|
||||
return false;
|
||||
}
|
||||
TEST(EVPExtraTest, d2i_PrivateKey) {
|
||||
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyDER,
|
||||
sizeof(kExampleRSAKeyDER)));
|
||||
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_DSA, kExampleDSAKeyDER,
|
||||
sizeof(kExampleDSAKeyDER)));
|
||||
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyPKCS8,
|
||||
sizeof(kExampleRSAKeyPKCS8)));
|
||||
EXPECT_TRUE(
|
||||
ParsePrivateKey(EVP_PKEY_EC, kExampleECKeyDER, sizeof(kExampleECKeyDER)));
|
||||
|
||||
derp = kExampleECKeyDER;
|
||||
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
|
||||
sizeof(kExampleECKeyDER)));
|
||||
if (!pkey || derp != kExampleECKeyDER + sizeof(kExampleECKeyDER)) {
|
||||
fprintf(stderr, "Failed to import raw EC key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
derp = kExampleBadECKeyDER;
|
||||
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
|
||||
sizeof(kExampleBadECKeyDER)));
|
||||
if (pkey) {
|
||||
fprintf(stderr, "Imported invalid EC key.\n");
|
||||
return false;
|
||||
}
|
||||
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleBadECKeyDER,
|
||||
sizeof(kExampleBadECKeyDER)));
|
||||
ERR_clear_error();
|
||||
|
||||
// Copy the input into a |malloc|'d vector to flag memory errors.
|
||||
std::vector<uint8_t> copy(kExampleBadECKeyDER2, kExampleBadECKeyDER2 +
|
||||
sizeof(kExampleBadECKeyDER2));
|
||||
derp = copy.data();
|
||||
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, copy.size()));
|
||||
if (pkey) {
|
||||
fprintf(stderr, "Imported invalid EC key #2.\n");
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t> copy(
|
||||
kExampleBadECKeyDER2,
|
||||
kExampleBadECKeyDER2 + sizeof(kExampleBadECKeyDER2));
|
||||
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, copy.data(), copy.size()));
|
||||
ERR_clear_error();
|
||||
|
||||
derp = kExampleRSAKeyPKCS8;
|
||||
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
|
||||
sizeof(kExampleRSAKeyPKCS8)));
|
||||
if (pkey) {
|
||||
fprintf(stderr, "Imported RSA key as EC key.\n");
|
||||
return false;
|
||||
}
|
||||
// Test that an RSA key may not be imported as an EC key.
|
||||
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleRSAKeyPKCS8,
|
||||
sizeof(kExampleRSAKeyPKCS8)));
|
||||
ERR_clear_error();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestEVP_DigestSignInit()) {
|
||||
fprintf(stderr, "EVP_DigestSignInit failed\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!TestEVP_DigestVerifyInit()) {
|
||||
fprintf(stderr, "EVP_DigestVerifyInit failed\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!TestVerifyRecover()) {
|
||||
fprintf(stderr, "EVP_PKEY_verify_recover failed\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!Testd2i_AutoPrivateKey()) {
|
||||
fprintf(stderr, "Testd2i_AutoPrivateKey failed\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!TestEVP_PKCS82PKEY()) {
|
||||
fprintf(stderr, "TestEVP_PKCS82PKEY failed\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!TestEVPMarshalEmptyPublicKey()) {
|
||||
fprintf(stderr, "TestEVPMarshalEmptyPublicKey failed\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!Testd2i_PrivateKey()) {
|
||||
fprintf(stderr, "Testd2i_PrivateKey failed\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -224,9 +224,8 @@ static bool TestEVP(FileTest *t, void *arg) {
|
||||
}
|
||||
EVP_PKEY *key = (*key_map)[key_name].get();
|
||||
|
||||
std::vector<uint8_t> input, output;
|
||||
if (!t->GetBytes(&input, "Input") ||
|
||||
!t->GetBytes(&output, "Output")) {
|
||||
std::vector<uint8_t> input;
|
||||
if (!t->GetBytes(&input, "Input")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -263,7 +262,9 @@ static bool TestEVP(FileTest *t, void *arg) {
|
||||
}
|
||||
|
||||
if (t->GetType() == "Verify") {
|
||||
if (!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
|
||||
std::vector<uint8_t> output;
|
||||
if (!t->GetBytes(&output, "Output") ||
|
||||
!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
|
||||
input.size())) {
|
||||
// ECDSA sometimes doesn't push an error code. Push one on the error queue
|
||||
// so it's distinguishable from other errors.
|
||||
@@ -274,7 +275,7 @@ static bool TestEVP(FileTest *t, void *arg) {
|
||||
}
|
||||
|
||||
size_t len;
|
||||
std::vector<uint8_t> actual;
|
||||
std::vector<uint8_t> actual, output;
|
||||
if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
|
||||
return false;
|
||||
}
|
||||
@@ -283,7 +284,8 @@ static bool TestEVP(FileTest *t, void *arg) {
|
||||
return false;
|
||||
}
|
||||
actual.resize(len);
|
||||
if (!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
|
||||
if (!t->GetBytes(&output, "Output") ||
|
||||
!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
+958
-4
File diff suppressed because it is too large
Load Diff
@@ -100,12 +100,6 @@ struct evp_pkey_asn1_method_st {
|
||||
* custom implementations which do not expose key material and parameters.*/
|
||||
int (*pkey_opaque)(const EVP_PKEY *pk);
|
||||
|
||||
/* pkey_supports_digest returns one if |pkey| supports digests of
|
||||
* type |md|. This is intended for use with EVP_PKEYs backing custom
|
||||
* implementations which can't sign all digests. If null, it is
|
||||
* assumed that all digests are supported. */
|
||||
int (*pkey_supports_digest)(const EVP_PKEY *pkey, const EVP_MD *md);
|
||||
|
||||
int (*pkey_size)(const EVP_PKEY *pk);
|
||||
int (*pkey_bits)(const EVP_PKEY *pk);
|
||||
|
||||
|
||||
@@ -151,7 +151,8 @@ static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
|
||||
/* Calculate the public key. */
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL ||
|
||||
!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
|
||||
!BN_mod_exp_mont(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx,
|
||||
NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -255,7 +256,6 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
|
||||
dsa_priv_encode,
|
||||
|
||||
NULL /* pkey_opaque */,
|
||||
NULL /* pkey_supports_digest */,
|
||||
|
||||
int_dsa_size,
|
||||
dsa_bits,
|
||||
|
||||
@@ -244,7 +244,6 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
|
||||
eckey_priv_encode,
|
||||
|
||||
eckey_opaque,
|
||||
0 /* pkey_supports_digest */,
|
||||
|
||||
int_ec_size,
|
||||
ec_bits,
|
||||
|
||||
+6
-13
@@ -386,22 +386,15 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out,
|
||||
}
|
||||
|
||||
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
|
||||
size_t plaintext_len;
|
||||
int message_len;
|
||||
|
||||
size_t padded_len;
|
||||
if (!setup_tbuf(rctx, ctx) ||
|
||||
!RSA_decrypt(rsa, &plaintext_len, rctx->tbuf, key_len, in, inlen,
|
||||
RSA_NO_PADDING)) {
|
||||
!RSA_decrypt(rsa, &padded_len, rctx->tbuf, key_len, in, inlen,
|
||||
RSA_NO_PADDING) ||
|
||||
!RSA_padding_check_PKCS1_OAEP_mgf1(
|
||||
out, outlen, key_len, rctx->tbuf, padded_len, rctx->oaep_label,
|
||||
rctx->oaep_labellen, rctx->md, rctx->mgf1md)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
message_len = RSA_padding_check_PKCS1_OAEP_mgf1(
|
||||
out, key_len, rctx->tbuf, plaintext_len, rctx->oaep_label,
|
||||
rctx->oaep_labellen, rctx->md, rctx->mgf1md);
|
||||
if (message_len < 0) {
|
||||
return 0;
|
||||
}
|
||||
*outlen = message_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,10 +162,6 @@ static int rsa_opaque(const EVP_PKEY *pkey) {
|
||||
return RSA_is_opaque(pkey->pkey.rsa);
|
||||
}
|
||||
|
||||
static int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
|
||||
return RSA_supports_digest(pkey->pkey.rsa, md);
|
||||
}
|
||||
|
||||
static int int_rsa_size(const EVP_PKEY *pkey) {
|
||||
return RSA_size(pkey->pkey.rsa);
|
||||
}
|
||||
@@ -189,7 +185,6 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
|
||||
rsa_priv_encode,
|
||||
|
||||
rsa_opaque,
|
||||
rsa_supports_digest,
|
||||
|
||||
int_rsa_size,
|
||||
rsa_bits,
|
||||
|
||||
+54
-61
@@ -65,83 +65,76 @@
|
||||
int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
|
||||
const uint8_t *salt, size_t salt_len, unsigned iterations,
|
||||
const EVP_MD *digest, size_t key_len, uint8_t *out_key) {
|
||||
uint8_t digest_tmp[EVP_MAX_MD_SIZE], *p, itmp[4];
|
||||
size_t cplen, mdlen, tkeylen, k;
|
||||
unsigned j;
|
||||
/* See RFC 8018, section 5.2. */
|
||||
int ret = 0;
|
||||
size_t md_len = EVP_MD_size(digest);
|
||||
uint32_t i = 1;
|
||||
HMAC_CTX hctx_tpl, hctx;
|
||||
HMAC_CTX hctx;
|
||||
HMAC_CTX_init(&hctx);
|
||||
|
||||
mdlen = EVP_MD_size(digest);
|
||||
HMAC_CTX_init(&hctx_tpl);
|
||||
p = out_key;
|
||||
tkeylen = key_len;
|
||||
if (!HMAC_Init_ex(&hctx_tpl, password, password_len, digest, NULL)) {
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
return 0;
|
||||
if (!HMAC_Init_ex(&hctx, password, password_len, digest, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
while (tkeylen) {
|
||||
if (tkeylen > mdlen) {
|
||||
cplen = mdlen;
|
||||
} else {
|
||||
cplen = tkeylen;
|
||||
|
||||
while (key_len > 0) {
|
||||
size_t todo = md_len;
|
||||
if (todo > key_len) {
|
||||
todo = key_len;
|
||||
}
|
||||
/* We are unlikely to ever use more than 256 blocks (5120 bits!)
|
||||
* but just in case... */
|
||||
itmp[0] = (uint8_t)((i >> 24) & 0xff);
|
||||
itmp[1] = (uint8_t)((i >> 16) & 0xff);
|
||||
itmp[2] = (uint8_t)((i >> 8) & 0xff);
|
||||
itmp[3] = (uint8_t)(i & 0xff);
|
||||
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
return 0;
|
||||
}
|
||||
if (!HMAC_Update(&hctx, salt, salt_len) ||
|
||||
!HMAC_Update(&hctx, itmp, 4) ||
|
||||
|
||||
uint8_t i_buf[4];
|
||||
i_buf[0] = (uint8_t)((i >> 24) & 0xff);
|
||||
i_buf[1] = (uint8_t)((i >> 16) & 0xff);
|
||||
i_buf[2] = (uint8_t)((i >> 8) & 0xff);
|
||||
i_buf[3] = (uint8_t)(i & 0xff);
|
||||
|
||||
/* Compute U_1. */
|
||||
uint8_t digest_tmp[EVP_MAX_MD_SIZE];
|
||||
if (!HMAC_Init_ex(&hctx, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&hctx, salt, salt_len) ||
|
||||
!HMAC_Update(&hctx, i_buf, 4) ||
|
||||
!HMAC_Final(&hctx, digest_tmp, NULL)) {
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
HMAC_CTX_cleanup(&hctx);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
HMAC_CTX_cleanup(&hctx);
|
||||
OPENSSL_memcpy(p, digest_tmp, cplen);
|
||||
for (j = 1; j < iterations; j++) {
|
||||
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
return 0;
|
||||
}
|
||||
if (!HMAC_Update(&hctx, digest_tmp, mdlen) ||
|
||||
|
||||
OPENSSL_memcpy(out_key, digest_tmp, todo);
|
||||
for (unsigned j = 1; j < iterations; j++) {
|
||||
/* Compute the remaining U_* values and XOR. */
|
||||
if (!HMAC_Init_ex(&hctx, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&hctx, digest_tmp, md_len) ||
|
||||
!HMAC_Final(&hctx, digest_tmp, NULL)) {
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
HMAC_CTX_cleanup(&hctx);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
HMAC_CTX_cleanup(&hctx);
|
||||
for (k = 0; k < cplen; k++) {
|
||||
p[k] ^= digest_tmp[k];
|
||||
for (size_t k = 0; k < todo; k++) {
|
||||
out_key[k] ^= digest_tmp[k];
|
||||
}
|
||||
}
|
||||
tkeylen -= cplen;
|
||||
|
||||
key_len -= todo;
|
||||
out_key += todo;
|
||||
i++;
|
||||
p += cplen;
|
||||
}
|
||||
HMAC_CTX_cleanup(&hctx_tpl);
|
||||
|
||||
// RFC 2898 describes iterations (c) as being a "positive integer", so a
|
||||
// value of 0 is an error.
|
||||
//
|
||||
// Unfortunatley not all consumers of PKCS5_PBKDF2_HMAC() check their return
|
||||
// value, expecting it to succeed and unconditonally using |out_key|.
|
||||
// As a precaution for such callsites in external code, the old behavior
|
||||
// of iterations < 1 being treated as iterations == 1 is preserved, but
|
||||
// additionally an error result is returned.
|
||||
//
|
||||
// TODO(eroman): Figure out how to remove this compatibility hack, or change
|
||||
// the default to something more sensible like 2048.
|
||||
/* RFC 8018 describes iterations (c) as being a "positive integer", so a
|
||||
* value of 0 is an error.
|
||||
*
|
||||
* Unfortunately not all consumers of PKCS5_PBKDF2_HMAC() check their return
|
||||
* value, expecting it to succeed and unconditionally using |out_key|. As a
|
||||
* precaution for such callsites in external code, the old behavior of
|
||||
* iterations < 1 being treated as iterations == 1 is preserved, but
|
||||
* additionally an error result is returned.
|
||||
*
|
||||
* TODO(eroman): Figure out how to remove this compatibility hack, or change
|
||||
* the default to something more sensible like 2048. */
|
||||
if (iterations == 0) {
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
HMAC_CTX_cleanup(&hctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PKCS5_PBKDF2_HMAC_SHA1(const char *password, size_t password_len,
|
||||
|
||||
+11
-1
@@ -239,6 +239,13 @@ int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to,
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ex_data_class->num_reserved; i++) {
|
||||
void *ptr = CRYPTO_get_ex_data(from, i);
|
||||
if (!CRYPTO_set_ex_data(to, i, ptr)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
|
||||
if (!get_func_pointers(&func_pointers, ex_data_class)) {
|
||||
return 0;
|
||||
@@ -252,7 +259,10 @@ int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to,
|
||||
func_pointer->dup_func(to, from, &ptr, i + ex_data_class->num_reserved,
|
||||
func_pointer->argl, func_pointer->argp);
|
||||
}
|
||||
CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr);
|
||||
if (!CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr)) {
|
||||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
|
||||
|
||||
@@ -69,15 +69,6 @@ uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
|
||||
const uint8_t *data, size_t data_len, uint8_t *out,
|
||||
unsigned int *out_len) {
|
||||
HMAC_CTX ctx;
|
||||
static uint8_t static_out_buffer[EVP_MAX_MD_SIZE];
|
||||
|
||||
/* OpenSSL has traditionally supported using a static buffer if |out| is
|
||||
* NULL. We maintain that but don't document it. This behaviour should be
|
||||
* considered to be deprecated. */
|
||||
if (out == NULL) {
|
||||
out = static_out_buffer;
|
||||
}
|
||||
|
||||
HMAC_CTX_init(&ctx);
|
||||
if (!HMAC_Init_ex(&ctx, key, key_len, evp_md, NULL) ||
|
||||
!HMAC_Update(&ctx, data, data_len) ||
|
||||
|
||||
+51
-43
@@ -183,17 +183,22 @@ static inline int buffers_alias(const uint8_t *a, size_t a_len,
|
||||
*
|
||||
* can be written as
|
||||
*
|
||||
* unsigned int lt = constant_time_lt(a, b);
|
||||
* c = constant_time_select(lt, a, b); */
|
||||
* size_t lt = constant_time_lt_s(a, b);
|
||||
* c = constant_time_select_s(lt, a, b); */
|
||||
|
||||
/* constant_time_msb returns the given value with the MSB copied to all the
|
||||
#define CONSTTIME_TRUE_S ~((size_t)0)
|
||||
#define CONSTTIME_FALSE_S ((size_t)0)
|
||||
#define CONSTTIME_TRUE_8 ((uint8_t)0xff)
|
||||
#define CONSTTIME_FALSE_8 ((uint8_t)0)
|
||||
|
||||
/* constant_time_msb_s returns the given value with the MSB copied to all the
|
||||
* other bits. */
|
||||
static inline unsigned int constant_time_msb(unsigned int a) {
|
||||
return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
|
||||
static inline size_t constant_time_msb_s(size_t a) {
|
||||
return 0u - (a >> (sizeof(a) * 8 - 1));
|
||||
}
|
||||
|
||||
/* constant_time_lt returns 0xff..f if a < b and 0 otherwise. */
|
||||
static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) {
|
||||
/* constant_time_lt_s returns 0xff..f if a < b and 0 otherwise. */
|
||||
static inline size_t constant_time_lt_s(size_t a, size_t b) {
|
||||
/* Consider the two cases of the problem:
|
||||
* msb(a) == msb(b): a < b iff the MSB of a - b is set.
|
||||
* msb(a) != msb(b): a < b iff the MSB of b is set.
|
||||
@@ -225,26 +230,28 @@ static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) {
|
||||
* (check-sat)
|
||||
* (get-model)
|
||||
*/
|
||||
return constant_time_msb(a^((a^b)|((a-b)^a)));
|
||||
return constant_time_msb_s(a^((a^b)|((a-b)^a)));
|
||||
}
|
||||
|
||||
/* constant_time_lt_8 acts like |constant_time_lt| but returns an 8-bit mask. */
|
||||
static inline uint8_t constant_time_lt_8(unsigned int a, unsigned int b) {
|
||||
return (uint8_t)(constant_time_lt(a, b));
|
||||
/* constant_time_lt_8 acts like |constant_time_lt_s| but returns an 8-bit
|
||||
* mask. */
|
||||
static inline uint8_t constant_time_lt_8(size_t a, size_t b) {
|
||||
return (uint8_t)(constant_time_lt_s(a, b));
|
||||
}
|
||||
|
||||
/* constant_time_gt returns 0xff..f if a >= b and 0 otherwise. */
|
||||
static inline unsigned int constant_time_ge(unsigned int a, unsigned int b) {
|
||||
return ~constant_time_lt(a, b);
|
||||
/* constant_time_ge_s returns 0xff..f if a >= b and 0 otherwise. */
|
||||
static inline size_t constant_time_ge_s(size_t a, size_t b) {
|
||||
return ~constant_time_lt_s(a, b);
|
||||
}
|
||||
|
||||
/* constant_time_ge_8 acts like |constant_time_ge| but returns an 8-bit mask. */
|
||||
static inline uint8_t constant_time_ge_8(unsigned int a, unsigned int b) {
|
||||
return (uint8_t)(constant_time_ge(a, b));
|
||||
/* constant_time_ge_8 acts like |constant_time_ge_s| but returns an 8-bit
|
||||
* mask. */
|
||||
static inline uint8_t constant_time_ge_8(size_t a, size_t b) {
|
||||
return (uint8_t)(constant_time_ge_s(a, b));
|
||||
}
|
||||
|
||||
/* constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. */
|
||||
static inline unsigned int constant_time_is_zero(unsigned int a) {
|
||||
static inline size_t constant_time_is_zero_s(size_t a) {
|
||||
/* Here is an SMT-LIB verification of this formula:
|
||||
*
|
||||
* (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32)
|
||||
@@ -257,41 +264,42 @@ static inline unsigned int constant_time_is_zero(unsigned int a) {
|
||||
* (check-sat)
|
||||
* (get-model)
|
||||
*/
|
||||
return constant_time_msb(~a & (a - 1));
|
||||
return constant_time_msb_s(~a & (a - 1));
|
||||
}
|
||||
|
||||
/* constant_time_is_zero_8 acts like constant_time_is_zero but returns an 8-bit
|
||||
/* constant_time_is_zero_8 acts like |constant_time_is_zero_s| but returns an
|
||||
* 8-bit mask. */
|
||||
static inline uint8_t constant_time_is_zero_8(size_t a) {
|
||||
return (uint8_t)(constant_time_is_zero_s(a));
|
||||
}
|
||||
|
||||
/* constant_time_eq_s returns 0xff..f if a == b and 0 otherwise. */
|
||||
static inline size_t constant_time_eq_s(size_t a, size_t b) {
|
||||
return constant_time_is_zero_s(a ^ b);
|
||||
}
|
||||
|
||||
/* constant_time_eq_8 acts like |constant_time_eq_s| but returns an 8-bit
|
||||
* mask. */
|
||||
static inline uint8_t constant_time_is_zero_8(unsigned int a) {
|
||||
return (uint8_t)(constant_time_is_zero(a));
|
||||
static inline uint8_t constant_time_eq_8(size_t a, size_t b) {
|
||||
return (uint8_t)(constant_time_eq_s(a, b));
|
||||
}
|
||||
|
||||
/* constant_time_eq returns 0xff..f if a == b and 0 otherwise. */
|
||||
static inline unsigned int constant_time_eq(unsigned int a, unsigned int b) {
|
||||
return constant_time_is_zero(a ^ b);
|
||||
}
|
||||
|
||||
/* constant_time_eq_8 acts like |constant_time_eq| but returns an 8-bit mask. */
|
||||
static inline uint8_t constant_time_eq_8(unsigned int a, unsigned int b) {
|
||||
return (uint8_t)(constant_time_eq(a, b));
|
||||
}
|
||||
|
||||
/* constant_time_eq_int acts like |constant_time_eq| but works on int values. */
|
||||
static inline unsigned int constant_time_eq_int(int a, int b) {
|
||||
return constant_time_eq((unsigned)(a), (unsigned)(b));
|
||||
/* constant_time_eq_int acts like |constant_time_eq_s| but works on int
|
||||
* values. */
|
||||
static inline size_t constant_time_eq_int(int a, int b) {
|
||||
return constant_time_eq_s((size_t)(a), (size_t)(b));
|
||||
}
|
||||
|
||||
/* constant_time_eq_int_8 acts like |constant_time_eq_int| but returns an 8-bit
|
||||
* mask. */
|
||||
static inline uint8_t constant_time_eq_int_8(int a, int b) {
|
||||
return constant_time_eq_8((unsigned)(a), (unsigned)(b));
|
||||
return constant_time_eq_8((size_t)(a), (size_t)(b));
|
||||
}
|
||||
|
||||
/* constant_time_select returns (mask & a) | (~mask & b). When |mask| is all 1s
|
||||
* or all 0s (as returned by the methods above), the select methods return
|
||||
/* constant_time_select_s returns (mask & a) | (~mask & b). When |mask| is all
|
||||
* 1s or all 0s (as returned by the methods above), the select methods return
|
||||
* either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). */
|
||||
static inline unsigned int constant_time_select(unsigned int mask,
|
||||
unsigned int a, unsigned int b) {
|
||||
static inline size_t constant_time_select_s(size_t mask, size_t a, size_t b) {
|
||||
return (mask & a) | (~mask & b);
|
||||
}
|
||||
|
||||
@@ -299,13 +307,13 @@ static inline unsigned int constant_time_select(unsigned int mask,
|
||||
* 8-bit values. */
|
||||
static inline uint8_t constant_time_select_8(uint8_t mask, uint8_t a,
|
||||
uint8_t b) {
|
||||
return (uint8_t)(constant_time_select(mask, a, b));
|
||||
return (uint8_t)(constant_time_select_s(mask, a, b));
|
||||
}
|
||||
|
||||
/* constant_time_select_int acts like |constant_time_select| but operates on
|
||||
* ints. */
|
||||
static inline int constant_time_select_int(unsigned int mask, int a, int b) {
|
||||
return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
|
||||
static inline int constant_time_select_int(size_t mask, int a, int b) {
|
||||
return (int)(constant_time_select_s(mask, (size_t)(a), (size_t)(b)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -65,13 +65,6 @@
|
||||
|
||||
uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
MD5_CTX ctx;
|
||||
static uint8_t digest[MD5_DIGEST_LENGTH];
|
||||
|
||||
/* TODO(fork): remove this static buffer. */
|
||||
if (out == NULL) {
|
||||
out = digest;
|
||||
}
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, data, len);
|
||||
MD5_Final(out, &ctx);
|
||||
|
||||
@@ -36,11 +36,11 @@ static void byte_reverse(polyval_block *b) {
|
||||
static void reverse_and_mulX_ghash(polyval_block *b) {
|
||||
uint64_t hi = b->u[0];
|
||||
uint64_t lo = b->u[1];
|
||||
const unsigned carry = constant_time_eq(hi & 1, 1);
|
||||
const size_t carry = constant_time_eq_s(hi & 1, 1);
|
||||
hi >>= 1;
|
||||
hi |= lo << 63;
|
||||
lo >>= 1;
|
||||
lo ^= ((uint64_t) constant_time_select(carry, 0xe1, 0)) << 56;
|
||||
lo ^= ((uint64_t) constant_time_select_s(carry, 0xe1, 0)) << 56;
|
||||
|
||||
b->u[0] = CRYPTO_bswap8(lo);
|
||||
b->u[1] = CRYPTO_bswap8(hi);
|
||||
|
||||
@@ -1134,7 +1134,7 @@ ___
|
||||
OPTION DOTNAME
|
||||
___
|
||||
}
|
||||
print STDOUT "#if defined(__x86_64__)\n" if ($gas);
|
||||
print STDOUT "#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)\n" if ($gas);
|
||||
|
||||
while(defined(my $line=<>)) {
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ add_library(
|
||||
OBJECT
|
||||
|
||||
pkcs8.c
|
||||
p8_pkey.c
|
||||
pkcs8_x509.c
|
||||
p5_pbev2.c
|
||||
)
|
||||
|
||||
|
||||
+26
-8
@@ -63,35 +63,53 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define PBE_UCS2_CONVERT_PASSWORD 0x1
|
||||
/* pkcs8_pbe_decrypt decrypts |in| using the PBE scheme described by
|
||||
* |algorithm|, which should be a serialized AlgorithmIdentifier structure. On
|
||||
* success, it sets |*out| to a newly-allocated buffer containing the decrypted
|
||||
* result and returns one. Otherwise, it returns zero. */
|
||||
int pkcs8_pbe_decrypt(uint8_t **out, size_t *out_len, CBS *algorithm,
|
||||
const char *pass, size_t pass_len, const uint8_t *in,
|
||||
size_t in_len);
|
||||
|
||||
#define PKCS12_KEY_ID 1
|
||||
#define PKCS12_IV_ID 2
|
||||
#define PKCS12_MAC_ID 3
|
||||
|
||||
/* pkcs12_key_gen runs the PKCS#12 key derivation function as specified in
|
||||
* RFC 7292, appendix B. On success, it writes the resulting |out_len| bytes of
|
||||
* key material to |out| and returns one. Otherwise, it returns zero. |id|
|
||||
* should be one of the |PKCS12_*_ID| values. */
|
||||
int pkcs12_key_gen(const char *pass, size_t pass_len, const uint8_t *salt,
|
||||
size_t salt_len, uint8_t id, unsigned iterations,
|
||||
size_t out_len, uint8_t *out, const EVP_MD *md);
|
||||
|
||||
struct pbe_suite {
|
||||
int pbe_nid;
|
||||
uint8_t oid[10];
|
||||
uint8_t oid_len;
|
||||
const EVP_CIPHER *(*cipher_func)(void);
|
||||
const EVP_MD *(*md_func)(void);
|
||||
/* decrypt_init initialize |ctx| for decrypting. The password is specified by
|
||||
* |pass_raw| and |pass_raw_len|. |param| contains the serialized parameters
|
||||
* field of the AlgorithmIdentifier.
|
||||
* |pass| and |pass_len|. |param| contains the serialized parameters field of
|
||||
* the AlgorithmIdentifier.
|
||||
*
|
||||
* It returns one on success and zero on error. */
|
||||
int (*decrypt_init)(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
||||
const uint8_t *pass_raw, size_t pass_raw_len, CBS *param);
|
||||
int flags;
|
||||
const char *pass, size_t pass_len, CBS *param);
|
||||
};
|
||||
|
||||
#define PKCS5_DEFAULT_ITERATIONS 2048
|
||||
#define PKCS5_SALT_LEN 8
|
||||
|
||||
int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
||||
const uint8_t *pass_raw, size_t pass_raw_len,
|
||||
CBS *param);
|
||||
const char *pass, size_t pass_len, CBS *param);
|
||||
|
||||
/* PKCS5_pbe2_encrypt_init configures |ctx| for encrypting with PKCS #5 PBES2,
|
||||
* as defined in RFC 2998, with the specified parameters. It writes the
|
||||
* corresponding AlgorithmIdentifier to |out|. */
|
||||
int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher, unsigned iterations,
|
||||
const uint8_t *pass_raw, size_t pass_raw_len,
|
||||
const char *pass, size_t pass_len,
|
||||
const uint8_t *salt, size_t salt_len);
|
||||
|
||||
|
||||
|
||||
+107
-26
@@ -62,16 +62,86 @@
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* 1.2.840.113549.1.5.12 */
|
||||
static const uint8_t kPBKDF2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x05, 0x0c};
|
||||
|
||||
/* 1.2.840.113549.1.5.13 */
|
||||
static const uint8_t kPBES2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x05, 0x0d};
|
||||
|
||||
/* 1.2.840.113549.2.7 */
|
||||
static const uint8_t kHMACWithSHA1[] = {0x2a, 0x86, 0x48, 0x86,
|
||||
0xf7, 0x0d, 0x02, 0x07};
|
||||
|
||||
static const struct {
|
||||
uint8_t oid[9];
|
||||
uint8_t oid_len;
|
||||
int nid;
|
||||
const EVP_CIPHER *(*cipher_func)(void);
|
||||
} kCipherOIDs[] = {
|
||||
/* 1.2.840.113549.3.2 */
|
||||
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02},
|
||||
8,
|
||||
NID_rc2_cbc,
|
||||
&EVP_rc2_cbc},
|
||||
/* 1.2.840.113549.3.7 */
|
||||
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07},
|
||||
8,
|
||||
NID_des_ede3_cbc,
|
||||
&EVP_des_ede3_cbc},
|
||||
/* 2.16.840.1.101.3.4.1.2 */
|
||||
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02},
|
||||
9,
|
||||
NID_aes_128_cbc,
|
||||
&EVP_aes_128_cbc},
|
||||
/* 2.16.840.1.101.3.4.1.22 */
|
||||
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16},
|
||||
9,
|
||||
NID_aes_192_cbc,
|
||||
&EVP_aes_192_cbc},
|
||||
/* 2.16.840.1.101.3.4.1.42 */
|
||||
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a},
|
||||
9,
|
||||
NID_aes_256_cbc,
|
||||
&EVP_aes_256_cbc},
|
||||
};
|
||||
|
||||
static const EVP_CIPHER *cbs_to_cipher(const CBS *cbs) {
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
|
||||
if (CBS_mem_equal(cbs, kCipherOIDs[i].oid, kCipherOIDs[i].oid_len)) {
|
||||
return kCipherOIDs[i].cipher_func();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int add_cipher_oid(CBB *out, int nid) {
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
|
||||
if (kCipherOIDs[i].nid == nid) {
|
||||
CBB child;
|
||||
return CBB_add_asn1(out, &child, CBS_ASN1_OBJECT) &&
|
||||
CBB_add_bytes(&child, kCipherOIDs[i].oid,
|
||||
kCipherOIDs[i].oid_len) &&
|
||||
CBB_flush(out);
|
||||
}
|
||||
}
|
||||
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
unsigned iterations, const uint8_t *pass_raw,
|
||||
size_t pass_raw_len, const uint8_t *salt,
|
||||
unsigned iterations, const char *pass,
|
||||
size_t pass_len, const uint8_t *salt,
|
||||
size_t salt_len, const uint8_t *iv,
|
||||
size_t iv_len, int enc) {
|
||||
if (iv_len != EVP_CIPHER_iv_length(cipher)) {
|
||||
@@ -80,8 +150,7 @@ static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
}
|
||||
|
||||
uint8_t key[EVP_MAX_KEY_LENGTH];
|
||||
int ret = PKCS5_PBKDF2_HMAC_SHA1((const char *)pass_raw, pass_raw_len, salt,
|
||||
salt_len, iterations,
|
||||
int ret = PKCS5_PBKDF2_HMAC_SHA1(pass, pass_len, salt, salt_len, iterations,
|
||||
EVP_CIPHER_key_length(cipher), key) &&
|
||||
EVP_CipherInit_ex(ctx, cipher, NULL /* engine */, key, iv, enc);
|
||||
OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
|
||||
@@ -90,7 +159,7 @@ static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
|
||||
int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher, unsigned iterations,
|
||||
const uint8_t *pass_raw, size_t pass_raw_len,
|
||||
const char *pass, size_t pass_len,
|
||||
const uint8_t *salt, size_t salt_len) {
|
||||
int cipher_nid = EVP_CIPHER_nid(cipher);
|
||||
if (cipher_nid == NID_undef) {
|
||||
@@ -105,12 +174,15 @@ int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
|
||||
}
|
||||
|
||||
/* See RFC 2898, appendix A. */
|
||||
CBB algorithm, param, kdf, kdf_param, salt_cbb, cipher_cbb, iv_cbb;
|
||||
CBB algorithm, oid, param, kdf, kdf_oid, kdf_param, salt_cbb, cipher_cbb,
|
||||
iv_cbb;
|
||||
if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) ||
|
||||
!OBJ_nid2cbb(&algorithm, NID_pbes2) ||
|
||||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
|
||||
!CBB_add_bytes(&oid, kPBES2, sizeof(kPBES2)) ||
|
||||
!CBB_add_asn1(&algorithm, ¶m, CBS_ASN1_SEQUENCE) ||
|
||||
!CBB_add_asn1(¶m, &kdf, CBS_ASN1_SEQUENCE) ||
|
||||
!OBJ_nid2cbb(&kdf, NID_id_pbkdf2) ||
|
||||
!CBB_add_asn1(&kdf, &kdf_oid, CBS_ASN1_OBJECT) ||
|
||||
!CBB_add_bytes(&kdf_oid, kPBKDF2, sizeof(kPBKDF2)) ||
|
||||
!CBB_add_asn1(&kdf, &kdf_param, CBS_ASN1_SEQUENCE) ||
|
||||
!CBB_add_asn1(&kdf_param, &salt_cbb, CBS_ASN1_OCTETSTRING) ||
|
||||
!CBB_add_bytes(&salt_cbb, salt, salt_len) ||
|
||||
@@ -120,7 +192,7 @@ int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
|
||||
!CBB_add_asn1_uint64(&kdf_param, EVP_CIPHER_key_length(cipher))) ||
|
||||
/* Omit the PRF. We use the default hmacWithSHA1. */
|
||||
!CBB_add_asn1(¶m, &cipher_cbb, CBS_ASN1_SEQUENCE) ||
|
||||
!OBJ_nid2cbb(&cipher_cbb, cipher_nid) ||
|
||||
!add_cipher_oid(&cipher_cbb, cipher_nid) ||
|
||||
/* RFC 2898 says RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and
|
||||
* IV, but OpenSSL always uses an OCTET STRING IV, so we do the same. */
|
||||
!CBB_add_asn1(&cipher_cbb, &iv_cbb, CBS_ASN1_OCTETSTRING) ||
|
||||
@@ -129,14 +201,13 @@ int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pkcs5_pbe2_cipher_init(ctx, cipher, iterations, pass_raw, pass_raw_len,
|
||||
salt, salt_len, iv,
|
||||
EVP_CIPHER_iv_length(cipher), 1 /* encrypt */);
|
||||
return pkcs5_pbe2_cipher_init(ctx, cipher, iterations, pass, pass_len, salt,
|
||||
salt_len, iv, EVP_CIPHER_iv_length(cipher),
|
||||
1 /* encrypt */);
|
||||
}
|
||||
|
||||
int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
||||
const uint8_t *pass_raw, size_t pass_raw_len,
|
||||
CBS *param) {
|
||||
const char *pass, size_t pass_len, CBS *param) {
|
||||
CBS pbe_param, kdf, kdf_obj, enc_scheme, enc_obj;
|
||||
if (!CBS_get_asn1(param, &pbe_param, CBS_ASN1_SEQUENCE) ||
|
||||
CBS_len(param) != 0 ||
|
||||
@@ -149,20 +220,20 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check that the key derivation function is PBKDF2. */
|
||||
if (OBJ_cbs2nid(&kdf_obj) != NID_id_pbkdf2) {
|
||||
/* Only PBKDF2 is supported. */
|
||||
if (!CBS_mem_equal(&kdf_obj, kPBKDF2, sizeof(kPBKDF2))) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See if we recognise the encryption algorithm. */
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbynid(OBJ_cbs2nid(&enc_obj));
|
||||
const EVP_CIPHER *cipher = cbs_to_cipher(&enc_obj);
|
||||
if (cipher == NULL) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse the KDF parameters. */
|
||||
/* Parse the KDF parameters. See RFC 8018, appendix A.2. */
|
||||
CBS pbkdf2_params, salt;
|
||||
uint64_t iterations;
|
||||
if (!CBS_get_asn1(&kdf, &pbkdf2_params, CBS_ASN1_SEQUENCE) ||
|
||||
@@ -194,8 +265,9 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
||||
}
|
||||
|
||||
if (CBS_len(&pbkdf2_params) != 0) {
|
||||
CBS prf;
|
||||
if (!CBS_get_asn1(&pbkdf2_params, &prf, CBS_ASN1_OBJECT) ||
|
||||
CBS alg_id, prf;
|
||||
if (!CBS_get_asn1(&pbkdf2_params, &alg_id, CBS_ASN1_SEQUENCE) ||
|
||||
!CBS_get_asn1(&alg_id, &prf, CBS_ASN1_OBJECT) ||
|
||||
CBS_len(&pbkdf2_params) != 0) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
||||
return 0;
|
||||
@@ -203,16 +275,25 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
||||
|
||||
/* We only support hmacWithSHA1. It is the DEFAULT, so DER requires it be
|
||||
* omitted, but we match OpenSSL in tolerating it being present. */
|
||||
if (OBJ_cbs2nid(&prf) != NID_hmacWithSHA1) {
|
||||
if (!CBS_mem_equal(&prf, kHMACWithSHA1, sizeof(kHMACWithSHA1))) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hmacWithSHA1 has a NULL parameter. */
|
||||
CBS null;
|
||||
if (!CBS_get_asn1(&alg_id, &null, CBS_ASN1_NULL) ||
|
||||
CBS_len(&null) != 0 ||
|
||||
CBS_len(&alg_id) != 0) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the encryption scheme parameters. Note OpenSSL does not match the
|
||||
* specification. Per RFC 2898, this should depend on the encryption scheme.
|
||||
* In particular, RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and IV.
|
||||
* We align with OpenSSL. */
|
||||
* In particular, RC2-CBC uses a SEQUENCE with version and IV. We align with
|
||||
* OpenSSL. */
|
||||
CBS iv;
|
||||
if (!CBS_get_asn1(&enc_scheme, &iv, CBS_ASN1_OCTETSTRING) ||
|
||||
CBS_len(&enc_scheme) != 0) {
|
||||
@@ -220,7 +301,7 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pkcs5_pbe2_cipher_init(ctx, cipher, (unsigned)iterations, pass_raw,
|
||||
pass_raw_len, CBS_data(&salt), CBS_len(&salt),
|
||||
return pkcs5_pbe2_cipher_init(ctx, cipher, (unsigned)iterations, pass,
|
||||
pass_len, CBS_data(&salt), CBS_len(&salt),
|
||||
CBS_data(&iv), CBS_len(&iv), 0 /* decrypt */);
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 1999.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-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 <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
/* Minor tweak to operation: zero private key data */
|
||||
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg) {
|
||||
/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
|
||||
if (operation == ASN1_OP_FREE_PRE) {
|
||||
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
|
||||
if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING &&
|
||||
key->pkey->value.octet_string) {
|
||||
OPENSSL_cleanse(key->pkey->value.octet_string->data,
|
||||
key->pkey->value.octet_string->length);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
|
||||
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
|
||||
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
|
||||
@@ -679,6 +679,225 @@ static const uint8_t kWindows[] = {
|
||||
0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
|
||||
};
|
||||
|
||||
/* kPBES2 is a PKCS#12 file using PBES2 created with:
|
||||
* openssl pkcs12 -export -inkey key.pem -in cert.pem -keypbe AES-128-CBC \
|
||||
* -certpbe AES-128-CBC */
|
||||
static const uint8_t kPBES2[] = {
|
||||
0x30, 0x82, 0x0a, 0x03, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0xc9, 0x06,
|
||||
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
|
||||
0x09, 0xba, 0x04, 0x82, 0x09, 0xb6, 0x30, 0x82, 0x09, 0xb2, 0x30, 0x82,
|
||||
0x04, 0x34, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
|
||||
0x06, 0xa0, 0x82, 0x04, 0x25, 0x30, 0x82, 0x04, 0x21, 0x02, 0x01, 0x00,
|
||||
0x30, 0x82, 0x04, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x07, 0x01, 0x30, 0x49, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x05, 0x0d, 0x30, 0x3c, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x0e, 0x04, 0x08, 0xdb,
|
||||
0x48, 0xe6, 0x98, 0x09, 0x8f, 0x6e, 0x2d, 0x02, 0x02, 0x08, 0x00, 0x30,
|
||||
0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02,
|
||||
0x04, 0x10, 0xee, 0xb3, 0x10, 0xe5, 0x21, 0x85, 0x03, 0x3e, 0x69, 0xad,
|
||||
0xdf, 0x78, 0xa7, 0xd8, 0xac, 0xf1, 0x80, 0x82, 0x03, 0xc0, 0xcb, 0x58,
|
||||
0x11, 0x28, 0x1d, 0xbc, 0x3c, 0x8c, 0xe7, 0x7b, 0x15, 0x67, 0x30, 0xf3,
|
||||
0x2b, 0x94, 0x10, 0x8c, 0xbe, 0xfd, 0xaa, 0x11, 0xd7, 0x99, 0xee, 0x21,
|
||||
0xb6, 0x1b, 0x4f, 0x53, 0xcb, 0x44, 0xff, 0x4f, 0xbf, 0xf6, 0x43, 0x3d,
|
||||
0x12, 0xe6, 0x09, 0xe8, 0x05, 0xdd, 0x2f, 0xc5, 0x39, 0xde, 0x0c, 0x88,
|
||||
0xe8, 0x4e, 0x89, 0x8f, 0x5f, 0xdf, 0x23, 0x50, 0xe6, 0xb7, 0xba, 0x1a,
|
||||
0xdd, 0x1c, 0x63, 0x51, 0x0e, 0x71, 0xb7, 0xf7, 0x39, 0x3c, 0xd4, 0xe7,
|
||||
0x52, 0x50, 0xc5, 0xd7, 0xbf, 0x65, 0x94, 0x72, 0x97, 0x2a, 0xb9, 0x68,
|
||||
0xc2, 0xbd, 0x0c, 0x97, 0x02, 0x74, 0x23, 0x7f, 0x11, 0x6b, 0xea, 0xb4,
|
||||
0xe4, 0x2f, 0xf0, 0x8b, 0x91, 0x5c, 0xdb, 0xae, 0x10, 0xbf, 0x89, 0xbc,
|
||||
0x62, 0xef, 0x99, 0xbf, 0x07, 0x59, 0x58, 0x12, 0xef, 0xaf, 0xe6, 0xcd,
|
||||
0x30, 0x27, 0xe4, 0xab, 0x44, 0xf7, 0xf9, 0x14, 0xb2, 0x5d, 0xfa, 0x97,
|
||||
0xe6, 0x9a, 0xed, 0x85, 0x60, 0x86, 0xd9, 0xb0, 0xd7, 0xa4, 0xe4, 0x00,
|
||||
0xa8, 0xee, 0xbb, 0xfc, 0x0d, 0xe8, 0x58, 0x7a, 0xca, 0x02, 0x1d, 0x02,
|
||||
0xab, 0xbd, 0x16, 0x50, 0x4f, 0xfc, 0x60, 0xde, 0x48, 0xb1, 0x7f, 0xea,
|
||||
0xba, 0x45, 0x7b, 0x29, 0xfe, 0x8e, 0xed, 0x48, 0xd2, 0x31, 0x64, 0xda,
|
||||
0x89, 0x84, 0x6f, 0xd1, 0xd2, 0xb1, 0x7b, 0x97, 0x19, 0x38, 0x16, 0xd9,
|
||||
0x3f, 0xd6, 0xdb, 0x6f, 0xab, 0x56, 0x34, 0xca, 0x34, 0x9c, 0x57, 0x41,
|
||||
0x6e, 0x87, 0x85, 0x2a, 0xa8, 0xfb, 0xe9, 0xf6, 0x3d, 0xb6, 0x83, 0x7b,
|
||||
0x02, 0xc9, 0xbe, 0xf1, 0xbb, 0x8e, 0xe5, 0x68, 0xae, 0xaa, 0xe1, 0x25,
|
||||
0x8d, 0x1f, 0x1f, 0x52, 0x45, 0x3e, 0xef, 0x33, 0xd8, 0x58, 0xd9, 0x48,
|
||||
0xd4, 0xb5, 0xe1, 0x53, 0x21, 0xb5, 0xbd, 0xd4, 0x63, 0x1f, 0xbf, 0xe4,
|
||||
0x30, 0x5e, 0xc3, 0x63, 0xce, 0xdc, 0x12, 0x8c, 0xc7, 0x0c, 0xea, 0x3b,
|
||||
0xf3, 0x0b, 0x38, 0x8d, 0xcc, 0x9b, 0xe7, 0xa0, 0x14, 0x5e, 0x48, 0x9c,
|
||||
0x74, 0x86, 0x8e, 0x2b, 0x77, 0x80, 0xbb, 0x85, 0xa6, 0xd4, 0x25, 0x6e,
|
||||
0x75, 0x07, 0x59, 0xd6, 0x88, 0x00, 0x35, 0x03, 0x5a, 0xb0, 0x86, 0x7e,
|
||||
0x01, 0xa7, 0x77, 0x74, 0x13, 0xfa, 0x9f, 0x2d, 0xe3, 0x90, 0xda, 0x68,
|
||||
0x23, 0x36, 0x0b, 0x62, 0x21, 0x76, 0xda, 0x6c, 0x05, 0x35, 0x80, 0xfc,
|
||||
0xee, 0x5f, 0x3c, 0xac, 0x60, 0x2a, 0x9c, 0x6e, 0x4c, 0xaa, 0xa3, 0xd1,
|
||||
0xdf, 0x2c, 0x7e, 0x0e, 0xc0, 0xa0, 0x84, 0xe4, 0xb2, 0x33, 0x1f, 0x8c,
|
||||
0xcb, 0x74, 0x31, 0x18, 0x5b, 0x0b, 0x18, 0x41, 0xc6, 0x87, 0x13, 0xa2,
|
||||
0xad, 0x1d, 0x43, 0x5e, 0x67, 0xd0, 0x31, 0xf5, 0x61, 0x7c, 0x3d, 0x16,
|
||||
0x55, 0x01, 0x94, 0x45, 0xa4, 0x50, 0x0f, 0xb1, 0x1b, 0x81, 0x51, 0xa7,
|
||||
0x92, 0xae, 0xa3, 0x6d, 0x4e, 0x55, 0x46, 0x37, 0x98, 0xe1, 0xe4, 0x5c,
|
||||
0x29, 0x79, 0xc9, 0x76, 0x0a, 0xb5, 0x9d, 0x1b, 0x8a, 0xf6, 0xab, 0xeb,
|
||||
0x69, 0x6e, 0x17, 0x88, 0xeb, 0x82, 0xfa, 0x78, 0x2f, 0x8c, 0x30, 0xfd,
|
||||
0xf1, 0x74, 0xcd, 0x53, 0x78, 0x27, 0x43, 0x82, 0x05, 0x37, 0x07, 0xb3,
|
||||
0x4c, 0x89, 0x9d, 0x00, 0x1d, 0x73, 0xad, 0x0f, 0xcd, 0x63, 0xbe, 0x9b,
|
||||
0xa9, 0x50, 0xa5, 0x43, 0x74, 0x86, 0x87, 0xbc, 0xd9, 0x97, 0x66, 0x84,
|
||||
0x35, 0x3e, 0x67, 0xce, 0x92, 0x2c, 0x78, 0xc7, 0x88, 0x19, 0x6a, 0x1c,
|
||||
0xa8, 0x93, 0x0b, 0x79, 0x21, 0xe5, 0x39, 0x1b, 0x00, 0x68, 0x2a, 0x0b,
|
||||
0xac, 0x6a, 0x2f, 0xc1, 0x9c, 0x90, 0x18, 0x86, 0x63, 0x53, 0x72, 0x34,
|
||||
0xd9, 0xa8, 0x92, 0xce, 0x64, 0x3a, 0xeb, 0xba, 0xd8, 0x31, 0xf3, 0xfb,
|
||||
0x2a, 0xac, 0xc6, 0xe7, 0xd1, 0x0b, 0x7c, 0xfc, 0xbb, 0x69, 0x57, 0xc8,
|
||||
0x97, 0x3d, 0xdb, 0x81, 0x77, 0x2a, 0x9f, 0x07, 0x2c, 0x79, 0x69, 0xbc,
|
||||
0x51, 0x0e, 0x68, 0x11, 0x00, 0x10, 0xed, 0x9f, 0xb8, 0x8d, 0xa0, 0x25,
|
||||
0x20, 0xd3, 0x3d, 0x08, 0x20, 0x46, 0xfa, 0x89, 0xef, 0x69, 0x4c, 0x60,
|
||||
0x33, 0x80, 0xb9, 0x53, 0xb4, 0x7b, 0xab, 0x38, 0xf1, 0xcd, 0xb8, 0x75,
|
||||
0xc4, 0x85, 0x0a, 0xda, 0xab, 0x19, 0x40, 0xd3, 0x88, 0xd5, 0xf7, 0x5f,
|
||||
0x8e, 0xcd, 0x8e, 0xa4, 0x1c, 0x9c, 0x22, 0x6d, 0xce, 0x66, 0x29, 0xfa,
|
||||
0x62, 0x6f, 0x01, 0xdc, 0x46, 0x45, 0x38, 0x64, 0xf7, 0xc4, 0x94, 0xfd,
|
||||
0x48, 0x44, 0x70, 0x4d, 0xef, 0xf0, 0x4b, 0x95, 0xf8, 0x68, 0x8d, 0xb7,
|
||||
0x35, 0x7d, 0xc6, 0xf5, 0x97, 0xce, 0x5d, 0xad, 0xe8, 0x5c, 0xeb, 0x4f,
|
||||
0x9b, 0x5b, 0x03, 0xce, 0x33, 0x60, 0xf5, 0xce, 0xcc, 0xfe, 0xfb, 0x77,
|
||||
0x40, 0xc4, 0xf4, 0x9d, 0xf3, 0x2c, 0xdb, 0x83, 0xc2, 0x1a, 0xf2, 0xb6,
|
||||
0xbe, 0xfc, 0x2c, 0x7f, 0x29, 0x20, 0x35, 0x50, 0x00, 0x60, 0x03, 0xd2,
|
||||
0xb3, 0x03, 0x18, 0x64, 0xb9, 0x64, 0x98, 0x33, 0xdb, 0x47, 0x43, 0xe2,
|
||||
0xa1, 0x85, 0x79, 0x9b, 0xb1, 0x0b, 0x0e, 0xbb, 0x14, 0x5f, 0xb9, 0x16,
|
||||
0xb6, 0xc3, 0xf6, 0x5c, 0x01, 0xe3, 0xaa, 0x3f, 0x03, 0xad, 0x18, 0xeb,
|
||||
0x0e, 0x3d, 0xa3, 0x1f, 0xcc, 0x4d, 0x48, 0x44, 0x7e, 0xda, 0xb9, 0x9d,
|
||||
0x17, 0xe8, 0x92, 0x46, 0xea, 0xf5, 0x3e, 0x05, 0x4e, 0xa7, 0xb5, 0x94,
|
||||
0x6d, 0x95, 0x42, 0xa7, 0x71, 0xfb, 0xc2, 0x45, 0xd6, 0xd2, 0x86, 0xd0,
|
||||
0x79, 0x99, 0x1f, 0x96, 0x78, 0x22, 0xeb, 0x05, 0x26, 0xf2, 0xa1, 0x67,
|
||||
0x67, 0x2b, 0xae, 0x1d, 0x28, 0x42, 0xd6, 0xbe, 0x08, 0xf6, 0xb7, 0x54,
|
||||
0xc8, 0x82, 0xbf, 0x92, 0x0f, 0x2c, 0xba, 0x47, 0xe2, 0x01, 0x73, 0x2c,
|
||||
0xd7, 0x34, 0x84, 0x2f, 0xb6, 0x41, 0x84, 0xeb, 0x7a, 0xb2, 0xf9, 0xdd,
|
||||
0x31, 0xbe, 0x07, 0xb4, 0x88, 0x05, 0xd8, 0xe1, 0x79, 0x55, 0xe6, 0x4b,
|
||||
0x8c, 0xdc, 0xd1, 0x76, 0x58, 0x72, 0x42, 0x28, 0xb3, 0x9f, 0xd0, 0x05,
|
||||
0x37, 0x6b, 0x65, 0x74, 0xce, 0x0d, 0x01, 0xa9, 0x49, 0xc5, 0x90, 0xab,
|
||||
0x90, 0x16, 0x2c, 0x9c, 0xba, 0xcb, 0x94, 0xc7, 0xfa, 0xe0, 0x39, 0x82,
|
||||
0xa2, 0x88, 0xd6, 0x0c, 0xc4, 0x4d, 0xfe, 0xb4, 0xbc, 0x87, 0xe5, 0x63,
|
||||
0x3b, 0x6b, 0xf0, 0xd1, 0x09, 0x39, 0x8f, 0x51, 0x4f, 0x32, 0xae, 0xed,
|
||||
0x0c, 0xff, 0x79, 0x52, 0x19, 0xa9, 0x4e, 0x45, 0x11, 0xc3, 0x5f, 0xd6,
|
||||
0x2b, 0x66, 0xe3, 0x9c, 0xbe, 0xbc, 0xda, 0x65, 0x25, 0xcd, 0xf5, 0x73,
|
||||
0x45, 0x09, 0xf5, 0x5d, 0x6b, 0x83, 0x45, 0x28, 0x98, 0x2c, 0x58, 0x44,
|
||||
0xca, 0x37, 0xeb, 0xc3, 0xc2, 0x10, 0x77, 0x14, 0x79, 0x9b, 0xd8, 0xb2,
|
||||
0xbf, 0x45, 0xd5, 0x63, 0xe4, 0x37, 0x42, 0x7b, 0x2d, 0xe2, 0x49, 0xb3,
|
||||
0x18, 0x8e, 0x86, 0x73, 0xf1, 0x59, 0x8a, 0xf2, 0x3c, 0x49, 0x12, 0x7b,
|
||||
0xb1, 0x40, 0x8c, 0x8c, 0xac, 0x05, 0x50, 0xbd, 0x9b, 0x3b, 0x84, 0x81,
|
||||
0x68, 0x26, 0x88, 0x1b, 0xbf, 0xa0, 0x28, 0xc2, 0x06, 0xa9, 0xe4, 0xd9,
|
||||
0x1f, 0x5d, 0xca, 0x96, 0x4f, 0xfe, 0xd8, 0x64, 0xee, 0x73, 0x30, 0x82,
|
||||
0x05, 0x76, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
|
||||
0x01, 0xa0, 0x82, 0x05, 0x67, 0x04, 0x82, 0x05, 0x63, 0x30, 0x82, 0x05,
|
||||
0x5f, 0x30, 0x82, 0x05, 0x5b, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x05, 0x23, 0x30, 0x82,
|
||||
0x05, 0x1f, 0x30, 0x49, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x05, 0x0d, 0x30, 0x3c, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||
0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x0e, 0x04, 0x08, 0xe3, 0x3e,
|
||||
0xd3, 0x8d, 0xd6, 0xb5, 0x8a, 0x05, 0x02, 0x02, 0x08, 0x00, 0x30, 0x1d,
|
||||
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02, 0x04,
|
||||
0x10, 0x61, 0xa0, 0x2f, 0x8d, 0x0c, 0xa1, 0x03, 0xc9, 0xdf, 0x2e, 0x81,
|
||||
0x65, 0xe0, 0x63, 0x70, 0x55, 0x04, 0x82, 0x04, 0xd0, 0x24, 0x1e, 0xf9,
|
||||
0x1d, 0xc4, 0xe9, 0xbf, 0x49, 0x3c, 0x1e, 0x55, 0x4a, 0xd4, 0xb0, 0x0c,
|
||||
0xdd, 0x5b, 0x92, 0xb2, 0xed, 0x18, 0xac, 0x66, 0x90, 0x1b, 0x29, 0x3d,
|
||||
0x10, 0xad, 0x02, 0xe7, 0x17, 0x83, 0x44, 0x67, 0xba, 0x11, 0x6f, 0x05,
|
||||
0xf5, 0xf7, 0x37, 0xcb, 0x5a, 0xe9, 0x0e, 0xc3, 0x4b, 0x1b, 0x62, 0xee,
|
||||
0xb2, 0xb7, 0x14, 0x85, 0x07, 0x2d, 0x95, 0x83, 0xa9, 0xdc, 0x3d, 0x4b,
|
||||
0x33, 0xad, 0x68, 0xbf, 0x54, 0xf8, 0xef, 0x25, 0x05, 0x40, 0xcd, 0x61,
|
||||
0xbe, 0x12, 0xeb, 0x78, 0x75, 0x36, 0x08, 0x8c, 0x5a, 0x57, 0xa1, 0x98,
|
||||
0xd5, 0x42, 0x01, 0x1b, 0x4c, 0x25, 0xc2, 0x18, 0x9f, 0x91, 0xfe, 0x78,
|
||||
0x88, 0x99, 0x47, 0x5a, 0x20, 0x2c, 0x37, 0x31, 0x05, 0x98, 0xef, 0x91,
|
||||
0x6e, 0xeb, 0x2e, 0x86, 0x90, 0x61, 0xb1, 0x57, 0x1a, 0x05, 0x82, 0x14,
|
||||
0x0c, 0xa8, 0x94, 0xae, 0x56, 0x7b, 0xd6, 0x2f, 0x8b, 0x2e, 0x91, 0xa6,
|
||||
0x12, 0x68, 0x1f, 0x06, 0x09, 0x2f, 0xa6, 0xed, 0x33, 0x99, 0x72, 0x56,
|
||||
0xe5, 0xf7, 0xea, 0xcc, 0xcf, 0x27, 0xa5, 0xad, 0x49, 0x5a, 0xbc, 0x7b,
|
||||
0xe3, 0x62, 0x63, 0x8f, 0x00, 0x2b, 0x96, 0xc5, 0x3f, 0xaf, 0x24, 0xba,
|
||||
0xf6, 0x8d, 0xe2, 0xef, 0x18, 0x50, 0xd6, 0xd8, 0x4f, 0xb2, 0x5d, 0xb7,
|
||||
0x96, 0x6f, 0x02, 0xf7, 0x7d, 0xf2, 0xa2, 0x7b, 0x9b, 0x13, 0x98, 0xde,
|
||||
0xdd, 0x6e, 0xb5, 0x48, 0x52, 0x8e, 0x44, 0xad, 0xe0, 0xcf, 0x40, 0x9f,
|
||||
0xfd, 0x88, 0x33, 0x66, 0xce, 0x6a, 0x49, 0x5f, 0xe7, 0x4b, 0x36, 0x93,
|
||||
0x7f, 0x49, 0x62, 0xc9, 0x5a, 0xae, 0xa1, 0xca, 0xf7, 0x5a, 0xbe, 0x85,
|
||||
0x77, 0x9a, 0x8f, 0xce, 0x4d, 0x84, 0x81, 0xd0, 0xa2, 0xee, 0x60, 0x92,
|
||||
0x86, 0x16, 0x2a, 0xd5, 0x08, 0xb6, 0x58, 0x63, 0x07, 0x7c, 0x41, 0xac,
|
||||
0x97, 0x4f, 0xf0, 0xcf, 0xd8, 0xd2, 0xb1, 0xd7, 0x1d, 0xe5, 0xb8, 0x7c,
|
||||
0x04, 0x2b, 0xd9, 0xee, 0xf7, 0x22, 0x88, 0xa1, 0x53, 0xdb, 0x5e, 0x5b,
|
||||
0x47, 0x49, 0xeb, 0xcf, 0x04, 0x78, 0x69, 0xd1, 0xfc, 0x8a, 0xa9, 0x61,
|
||||
0x92, 0xbf, 0x5c, 0x7f, 0xde, 0x49, 0x42, 0xfc, 0x0d, 0xc2, 0xa2, 0x8f,
|
||||
0xba, 0xdf, 0x12, 0xa4, 0x62, 0xfb, 0x8d, 0xd3, 0xc5, 0xf9, 0x85, 0x4c,
|
||||
0x17, 0x70, 0xb7, 0xf7, 0x99, 0x29, 0x52, 0x92, 0x36, 0xc5, 0x4b, 0x31,
|
||||
0x23, 0x5c, 0x09, 0x27, 0x3c, 0xa0, 0x76, 0x5d, 0x92, 0x99, 0x63, 0x88,
|
||||
0xca, 0xad, 0xed, 0xd7, 0x85, 0x98, 0x2f, 0xbe, 0xaa, 0xa5, 0xf3, 0x0a,
|
||||
0x76, 0x13, 0x01, 0x90, 0x8a, 0xe7, 0x5a, 0x2d, 0x2b, 0x1a, 0x80, 0x33,
|
||||
0x86, 0xab, 0xd8, 0xa7, 0xae, 0x0b, 0x7d, 0xcd, 0x64, 0x8d, 0xa6, 0xb6,
|
||||
0xfb, 0x83, 0x9f, 0x91, 0x23, 0xcb, 0xda, 0x63, 0xd0, 0xde, 0xf4, 0xdd,
|
||||
0xaa, 0x23, 0x49, 0x6c, 0x44, 0xfa, 0x6f, 0x12, 0x13, 0x90, 0x37, 0xde,
|
||||
0xa3, 0x72, 0x45, 0x1a, 0xa7, 0xab, 0x01, 0x6d, 0xd6, 0x34, 0xe7, 0x51,
|
||||
0x0e, 0x33, 0xbc, 0x09, 0xbf, 0xb6, 0x16, 0xf8, 0xd3, 0x11, 0x11, 0xd1,
|
||||
0x5f, 0xaa, 0x32, 0xb6, 0x5b, 0xe7, 0xbc, 0xdd, 0xaa, 0xe4, 0xed, 0x42,
|
||||
0x3d, 0x2e, 0xf7, 0xa1, 0x06, 0x39, 0xd4, 0x00, 0xc6, 0xc8, 0xed, 0xb5,
|
||||
0x96, 0xc1, 0xbf, 0x4c, 0xf1, 0xf6, 0xc6, 0x59, 0xf4, 0x99, 0x9c, 0x10,
|
||||
0x22, 0xa1, 0x3a, 0xcd, 0x94, 0xac, 0x0b, 0xc8, 0x7e, 0x29, 0xbc, 0xf0,
|
||||
0xae, 0x27, 0x7a, 0xb8, 0x5c, 0xa0, 0x13, 0x36, 0xb5, 0x19, 0x4b, 0x2c,
|
||||
0xc1, 0xce, 0x49, 0x57, 0x1d, 0x36, 0xf0, 0xc2, 0x4c, 0xdf, 0x6d, 0xc9,
|
||||
0x64, 0x68, 0xcb, 0xea, 0x22, 0x32, 0xd7, 0x11, 0x2c, 0x77, 0xbe, 0x01,
|
||||
0xa3, 0x82, 0x2d, 0xa1, 0x4b, 0x13, 0x93, 0x87, 0x3d, 0x01, 0x74, 0xc6,
|
||||
0xc6, 0xf9, 0xae, 0x2e, 0xa1, 0x44, 0x5d, 0x47, 0x6c, 0x6f, 0xc6, 0xce,
|
||||
0xef, 0x32, 0xf8, 0x8d, 0x53, 0x4d, 0xa5, 0xf0, 0xa0, 0x51, 0x7e, 0xd8,
|
||||
0x35, 0x55, 0x2a, 0x04, 0xb9, 0x42, 0xa7, 0x51, 0xba, 0xad, 0xce, 0x88,
|
||||
0x7b, 0x93, 0x25, 0x9d, 0x03, 0x08, 0xfa, 0x75, 0x38, 0x63, 0x78, 0x13,
|
||||
0x11, 0x9d, 0xf6, 0xcc, 0x18, 0xe3, 0x99, 0xa9, 0x5d, 0x90, 0x6b, 0xbf,
|
||||
0x9c, 0x69, 0x99, 0x63, 0x27, 0x35, 0x8a, 0x26, 0x07, 0x67, 0xd1, 0xae,
|
||||
0x57, 0xec, 0xc0, 0x45, 0x6e, 0x2a, 0x42, 0x46, 0x8f, 0xe4, 0x84, 0xc7,
|
||||
0x67, 0x06, 0x0c, 0xa7, 0x7e, 0x5c, 0x20, 0x80, 0xdc, 0xc1, 0xe4, 0x7a,
|
||||
0x74, 0x76, 0x8f, 0x41, 0x78, 0xce, 0x6a, 0xf9, 0xcb, 0x7f, 0xe9, 0x17,
|
||||
0x70, 0x45, 0x01, 0x9a, 0xc3, 0x9c, 0xa2, 0x68, 0xa0, 0x79, 0xfd, 0x44,
|
||||
0x4c, 0xc8, 0xa0, 0xaf, 0xa5, 0xba, 0x0f, 0x03, 0x30, 0x43, 0x4a, 0x1d,
|
||||
0x3e, 0xd4, 0x8e, 0x1f, 0x6d, 0x09, 0xf9, 0x63, 0xde, 0xd2, 0x9e, 0x77,
|
||||
0xe7, 0xde, 0x61, 0x52, 0x76, 0x0f, 0x6d, 0x37, 0xf7, 0xc2, 0x69, 0x96,
|
||||
0x9d, 0xc5, 0xd9, 0x15, 0x10, 0xf2, 0x22, 0x1f, 0x3b, 0x83, 0xb3, 0xb4,
|
||||
0x2c, 0x25, 0x36, 0xc3, 0x3a, 0x24, 0x17, 0xed, 0xad, 0x11, 0x1f, 0x46,
|
||||
0x31, 0x0c, 0x6a, 0x3c, 0xd2, 0x1a, 0xe7, 0x41, 0xb3, 0x75, 0xd8, 0x80,
|
||||
0xb3, 0xf8, 0x2b, 0xab, 0xb5, 0x81, 0xc6, 0x5e, 0x40, 0x9a, 0x77, 0xaa,
|
||||
0x79, 0x31, 0x1f, 0x79, 0xfe, 0x0f, 0x0f, 0xb0, 0x36, 0xb7, 0xdc, 0xca,
|
||||
0xf6, 0xbf, 0x80, 0xeb, 0x78, 0xc6, 0x73, 0x6a, 0xb3, 0x71, 0x69, 0x9c,
|
||||
0x1d, 0xdd, 0x90, 0xd9, 0x73, 0x07, 0x43, 0x37, 0x19, 0x7f, 0x22, 0xa4,
|
||||
0x9a, 0x4d, 0x98, 0x66, 0x10, 0x5b, 0x08, 0x62, 0xb3, 0xd8, 0x2f, 0x56,
|
||||
0x68, 0x22, 0xdf, 0xd1, 0xa2, 0x5a, 0x45, 0xf9, 0xb4, 0xb9, 0xf2, 0x48,
|
||||
0x4e, 0x38, 0x1a, 0x23, 0x36, 0x6d, 0x42, 0x56, 0xbb, 0x32, 0xe3, 0x00,
|
||||
0x84, 0xa9, 0xe2, 0xba, 0xb6, 0x86, 0xc9, 0xa6, 0x64, 0x8a, 0xd6, 0xa6,
|
||||
0xc4, 0xd7, 0x3e, 0x8b, 0x34, 0x1b, 0x6b, 0x65, 0xfe, 0xb1, 0xc9, 0x93,
|
||||
0xe1, 0xeb, 0x8a, 0x3b, 0xf1, 0x0f, 0xdb, 0x84, 0xe2, 0x2d, 0xf8, 0x69,
|
||||
0x04, 0xee, 0xaf, 0x58, 0x2f, 0xc7, 0x96, 0x70, 0x4d, 0xd9, 0x4c, 0x1d,
|
||||
0x52, 0x38, 0xc6, 0x26, 0x27, 0x41, 0x38, 0x0b, 0xa5, 0x1c, 0x16, 0xd0,
|
||||
0x1d, 0x32, 0x99, 0xb9, 0x1f, 0x35, 0xaf, 0x02, 0xb0, 0x13, 0x0f, 0x95,
|
||||
0xd3, 0x9b, 0xd6, 0x09, 0xcc, 0x29, 0x46, 0xe8, 0xf1, 0x54, 0x4d, 0xb8,
|
||||
0x96, 0xa6, 0x0d, 0x59, 0x61, 0x1f, 0xee, 0xaf, 0xbc, 0x23, 0x58, 0xff,
|
||||
0xcf, 0x96, 0x91, 0x1f, 0x00, 0x80, 0x4e, 0x9a, 0xa2, 0xe0, 0x00, 0xf7,
|
||||
0x3e, 0xb1, 0x91, 0x6c, 0x29, 0x58, 0x5e, 0xe7, 0xc7, 0x23, 0xfa, 0x88,
|
||||
0xf7, 0xfb, 0x0b, 0x0e, 0x4a, 0x04, 0x46, 0xe0, 0x67, 0x10, 0x09, 0xea,
|
||||
0xc0, 0xa9, 0xbe, 0x83, 0x11, 0x33, 0x8e, 0xfb, 0xd6, 0xd5, 0x67, 0xef,
|
||||
0xb4, 0x13, 0x4d, 0x17, 0xa1, 0x44, 0xb7, 0x98, 0x77, 0xd0, 0x63, 0xe7,
|
||||
0x9c, 0xa7, 0x96, 0x29, 0xe5, 0xfe, 0x72, 0x4c, 0xa9, 0x85, 0x9b, 0xc9,
|
||||
0xf3, 0xf6, 0x05, 0x0a, 0x28, 0x68, 0x99, 0x31, 0xe8, 0x64, 0x30, 0x9c,
|
||||
0x2a, 0x90, 0x48, 0x84, 0x00, 0x1a, 0x66, 0x0e, 0x3e, 0xf7, 0xaa, 0xc9,
|
||||
0x6c, 0x5b, 0x57, 0x7b, 0xa9, 0x17, 0x91, 0x1e, 0x6b, 0xe8, 0x12, 0xa1,
|
||||
0xd4, 0xde, 0x1e, 0x38, 0x14, 0x7b, 0xe0, 0x9a, 0x15, 0xae, 0x5a, 0x26,
|
||||
0x93, 0x7a, 0xd6, 0x8d, 0x26, 0x61, 0x28, 0xf2, 0x40, 0x71, 0xc7, 0x8a,
|
||||
0x2d, 0x69, 0x72, 0x04, 0x5b, 0xb9, 0xc1, 0x7b, 0x17, 0xde, 0x2c, 0xfc,
|
||||
0xa9, 0xf2, 0xf8, 0x34, 0x33, 0x09, 0x87, 0x91, 0xdf, 0xeb, 0xf7, 0x57,
|
||||
0x5b, 0x32, 0xe2, 0xd4, 0xe4, 0x47, 0x78, 0xe8, 0x9b, 0x1a, 0xab, 0x44,
|
||||
0x55, 0x28, 0x98, 0x20, 0xa7, 0x16, 0x8b, 0x4e, 0x42, 0xf1, 0x91, 0xbe,
|
||||
0x00, 0x87, 0x3a, 0x91, 0x63, 0x9a, 0xc2, 0x8d, 0x13, 0x34, 0x8b, 0x33,
|
||||
0x02, 0x88, 0x1e, 0xb1, 0xa8, 0x07, 0x6d, 0xb1, 0xf5, 0xb3, 0x7a, 0x3d,
|
||||
0x17, 0x3f, 0xbd, 0xa1, 0xdb, 0x04, 0x0f, 0x29, 0x7b, 0x0e, 0x98, 0x18,
|
||||
0x63, 0x0b, 0x60, 0xcd, 0xa5, 0x0d, 0x5f, 0x1e, 0x53, 0xcd, 0xfa, 0xc0,
|
||||
0xc7, 0x99, 0x53, 0x5f, 0xb7, 0xe5, 0x4a, 0x30, 0xde, 0x14, 0xc9, 0x49,
|
||||
0x46, 0x31, 0xb6, 0x92, 0xf3, 0x4b, 0xc1, 0xb0, 0xdd, 0xec, 0x48, 0xff,
|
||||
0x2d, 0x52, 0x53, 0x64, 0x27, 0x4c, 0x78, 0x96, 0x80, 0x90, 0xa3, 0xd7,
|
||||
0xfd, 0x7a, 0x23, 0x36, 0xa0, 0x76, 0x9e, 0x96, 0xfc, 0xcd, 0xec, 0x58,
|
||||
0xf8, 0x76, 0x4b, 0x2f, 0x8d, 0xb9, 0xd6, 0x89, 0xa1, 0x57, 0xe1, 0xc6,
|
||||
0xed, 0x9a, 0x1e, 0xde, 0xc7, 0x68, 0x93, 0x2b, 0x2e, 0x84, 0x1a, 0xf9,
|
||||
0x8c, 0x58, 0xb8, 0xf0, 0x29, 0xfe, 0x7b, 0x03, 0x84, 0xe8, 0x52, 0x1c,
|
||||
0x01, 0xbb, 0xcc, 0x5d, 0x88, 0xcd, 0x37, 0x8b, 0xe2, 0x2d, 0x30, 0xd1,
|
||||
0xbe, 0xf7, 0xc1, 0x95, 0xb7, 0x01, 0x43, 0xab, 0x30, 0x3f, 0x96, 0x47,
|
||||
0x6d, 0x52, 0x29, 0x87, 0x10, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14,
|
||||
0x14, 0x74, 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3,
|
||||
0x7e, 0x33, 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x30, 0x31, 0x30, 0x21,
|
||||
0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
|
||||
0x14, 0x2f, 0x5c, 0xc6, 0xaf, 0xa7, 0xcc, 0xb5, 0x77, 0x40, 0xca, 0x71,
|
||||
0xc3, 0x8c, 0xc6, 0x69, 0xdc, 0xc6, 0x7f, 0x54, 0xef, 0x04, 0x08, 0xf8,
|
||||
0x9c, 0x8b, 0x12, 0x27, 0xe8, 0xec, 0x65, 0x02, 0x02, 0x08, 0x00};
|
||||
|
||||
static const char kPassword[] = "foo";
|
||||
|
||||
static bool Test(const char *name, const uint8_t *der, size_t der_len) {
|
||||
@@ -759,6 +978,7 @@ int main(int argc, char **argv) {
|
||||
if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
|
||||
!Test("NSS", kNSS, sizeof(kNSS)) ||
|
||||
!Test("Windows", kWindows, sizeof(kWindows)) ||
|
||||
!Test("PBES2", kPBES2, sizeof(kPBES2)) ||
|
||||
!TestCompat(kWindows, sizeof(kWindows))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+127
-830
File diff suppressed because it is too large
Load Diff
@@ -143,6 +143,31 @@ static const uint8_t kEmptyPasswordOpenSSL[] = {
|
||||
0xed,
|
||||
};
|
||||
|
||||
// kExplicitHMACWithSHA1 is a PBES2-encrypted private key with an explicit
|
||||
// hmacWithSHA1 AlgorithmIdentifier in the PBKDF2 parameters.
|
||||
static const uint8_t kExplicitHMACWithSHA1[] = {
|
||||
0x30, 0x81, 0xec, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x05, 0x0d, 0x30, 0x4a, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x1c, 0x04, 0x08, 0x90,
|
||||
0xcd, 0x1e, 0x47, 0x1d, 0xff, 0x4c, 0xa8, 0x02, 0x02, 0x08, 0x00, 0x30,
|
||||
0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07, 0x05,
|
||||
0x00, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
|
||||
0x01, 0x02, 0x04, 0x10, 0x34, 0xe7, 0x5b, 0x9b, 0xf9, 0x17, 0xcf, 0x15,
|
||||
0x59, 0x7c, 0xfd, 0xc1, 0xac, 0xed, 0x6f, 0xdd, 0x04, 0x81, 0x90, 0xe3,
|
||||
0xd7, 0xfc, 0xbe, 0xe6, 0xe8, 0x92, 0xc1, 0xa2, 0x57, 0x42, 0x4b, 0xf1,
|
||||
0x35, 0x6c, 0x4f, 0x58, 0x61, 0x14, 0x30, 0x4e, 0xa3, 0x8d, 0x4f, 0xde,
|
||||
0x2d, 0x0b, 0xa2, 0x62, 0x4b, 0xee, 0x9f, 0xc4, 0xeb, 0x89, 0x33, 0x76,
|
||||
0x3f, 0x0c, 0x20, 0xad, 0x75, 0x29, 0x42, 0xbc, 0xbd, 0x83, 0x46, 0x1d,
|
||||
0x5c, 0xae, 0xec, 0x10, 0x05, 0xbb, 0xd3, 0x98, 0xc9, 0x5a, 0x5e, 0x0a,
|
||||
0x95, 0x12, 0x1e, 0x65, 0x93, 0xdd, 0xdd, 0x51, 0xd5, 0x56, 0xc2, 0xa9,
|
||||
0xf9, 0x43, 0x0f, 0x68, 0x8a, 0x14, 0x40, 0xe5, 0x62, 0x9e, 0x0d, 0xd7,
|
||||
0x67, 0x62, 0xf4, 0x49, 0xb1, 0x62, 0x22, 0x42, 0xb1, 0xe1, 0xb2, 0x1d,
|
||||
0x37, 0x3e, 0x95, 0x52, 0xe9, 0x61, 0x89, 0xc7, 0x62, 0xcc, 0xb1, 0x44,
|
||||
0x40, 0xef, 0x89, 0xc8, 0xc4, 0x0e, 0xae, 0xa8, 0xf9, 0x17, 0x42, 0x2b,
|
||||
0x8c, 0x0b, 0x26, 0xf6, 0x07, 0x00, 0xab, 0x25, 0x2b, 0x64, 0xcf, 0xc3,
|
||||
0x68, 0xf9, 0x5e, 0x01, 0x66, 0x59, 0x5f, 0x3f, 0x05, 0x57, 0xcd,
|
||||
};
|
||||
|
||||
static bool TestDecrypt(const uint8_t *der, size_t der_len,
|
||||
const char *password) {
|
||||
const uint8_t *data = der;
|
||||
@@ -222,6 +247,8 @@ int main(int argc, char **argv) {
|
||||
!TestDecrypt(kNullPassword, sizeof(kNullPassword), NULL) ||
|
||||
!TestDecrypt(kNullPasswordNSS, sizeof(kNullPasswordNSS), NULL) ||
|
||||
!TestDecrypt(kEmptyPasswordOpenSSL, sizeof(kEmptyPasswordOpenSSL), "") ||
|
||||
!TestDecrypt(kExplicitHMACWithSHA1, sizeof(kExplicitHMACWithSHA1),
|
||||
"foo") ||
|
||||
!TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr,
|
||||
"password", nullptr, 0, 10) ||
|
||||
// Vary the salt
|
||||
|
||||
@@ -0,0 +1,790 @@
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 1999.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999 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 <openssl/pkcs8.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../bytestring/internal.h"
|
||||
#include "../digest/internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Minor tweak to operation: zero private key data */
|
||||
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg) {
|
||||
/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
|
||||
if (operation == ASN1_OP_FREE_PRE) {
|
||||
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
|
||||
if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING &&
|
||||
key->pkey->value.octet_string) {
|
||||
OPENSSL_cleanse(key->pkey->value.octet_string->data,
|
||||
key->pkey->value.octet_string->length);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
|
||||
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
|
||||
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
|
||||
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
|
||||
|
||||
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
|
||||
uint8_t *der = NULL;
|
||||
int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der);
|
||||
if (der_len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, der, (size_t)der_len);
|
||||
EVP_PKEY *ret = EVP_parse_private_key(&cbs);
|
||||
if (ret == NULL || CBS_len(&cbs) != 0) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
||||
EVP_PKEY_free(ret);
|
||||
OPENSSL_free(der);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_free(der);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
|
||||
CBB cbb;
|
||||
uint8_t *der = NULL;
|
||||
size_t der_len;
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
!EVP_marshal_private_key(&cbb, pkey) ||
|
||||
!CBB_finish(&cbb, &der, &der_len) ||
|
||||
der_len > LONG_MAX) {
|
||||
CBB_cleanup(&cbb);
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
const uint8_t *p = der;
|
||||
PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len);
|
||||
if (p8 == NULL || p != der + der_len) {
|
||||
PKCS8_PRIV_KEY_INFO_free(p8);
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
OPENSSL_free(der);
|
||||
return p8;
|
||||
|
||||
err:
|
||||
OPENSSL_free(der);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
|
||||
int pass_len_in) {
|
||||
size_t pass_len;
|
||||
if (pass_len_in == -1 && pass != NULL) {
|
||||
pass_len = strlen(pass);
|
||||
} else {
|
||||
pass_len = (size_t)pass_len_in;
|
||||
}
|
||||
|
||||
PKCS8_PRIV_KEY_INFO *ret = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
uint8_t *in = NULL;
|
||||
|
||||
/* Convert the legacy ASN.1 object to a byte string. */
|
||||
int in_len = i2d_X509_SIG(pkcs8, &in);
|
||||
if (in_len < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, in, in_len);
|
||||
pkey = PKCS8_parse_encrypted_private_key(&cbs, pass, pass_len);
|
||||
if (pkey == NULL || CBS_len(&cbs) != 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = EVP_PKEY2PKCS8(pkey);
|
||||
|
||||
err:
|
||||
OPENSSL_free(in);
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
|
||||
int pass_len_in, const uint8_t *salt, size_t salt_len,
|
||||
int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
|
||||
size_t pass_len;
|
||||
if (pass_len_in == -1 && pass != NULL) {
|
||||
pass_len = strlen(pass);
|
||||
} else {
|
||||
pass_len = (size_t)pass_len_in;
|
||||
}
|
||||
|
||||
/* Parse out the private key. */
|
||||
EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
|
||||
if (pkey == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
X509_SIG *ret = NULL;
|
||||
uint8_t *der = NULL;
|
||||
size_t der_len;
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, 128) ||
|
||||
!PKCS8_marshal_encrypted_private_key(&cbb, pbe_nid, cipher, pass,
|
||||
pass_len, salt, salt_len, iterations,
|
||||
pkey) ||
|
||||
!CBB_finish(&cbb, &der, &der_len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Convert back to legacy ASN.1 objects. */
|
||||
const uint8_t *ptr = der;
|
||||
ret = d2i_X509_SIG(NULL, &ptr, der_len);
|
||||
if (ret == NULL || ptr != der + der_len) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, ERR_R_INTERNAL_ERROR);
|
||||
X509_SIG_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
err:
|
||||
OPENSSL_free(der);
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct pkcs12_context {
|
||||
EVP_PKEY **out_key;
|
||||
STACK_OF(X509) *out_certs;
|
||||
const char *password;
|
||||
size_t password_len;
|
||||
};
|
||||
|
||||
/* PKCS12_handle_sequence parses a BER-encoded SEQUENCE of elements in a PKCS#12
|
||||
* structure. */
|
||||
static int PKCS12_handle_sequence(
|
||||
CBS *sequence, struct pkcs12_context *ctx,
|
||||
int (*handle_element)(CBS *cbs, struct pkcs12_context *ctx)) {
|
||||
uint8_t *der_bytes = NULL;
|
||||
size_t der_len;
|
||||
CBS in;
|
||||
int ret = 0;
|
||||
|
||||
/* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|,
|
||||
* the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the
|
||||
* conversion cannot see through those wrappings. So each time we step
|
||||
* through one we need to convert to DER again. */
|
||||
if (!CBS_asn1_ber_to_der(sequence, &der_bytes, &der_len)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (der_bytes != NULL) {
|
||||
CBS_init(&in, der_bytes, der_len);
|
||||
} else {
|
||||
CBS_init(&in, CBS_data(sequence), CBS_len(sequence));
|
||||
}
|
||||
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(&in, &child, CBS_ASN1_SEQUENCE) ||
|
||||
CBS_len(&in) != 0) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (CBS_len(&child) > 0) {
|
||||
CBS element;
|
||||
if (!CBS_get_asn1(&child, &element, CBS_ASN1_SEQUENCE)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!handle_element(&element, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(der_bytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 1.2.840.113549.1.12.10.1.2 */
|
||||
static const uint8_t kPKCS8ShroudedKeyBag[] = {
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02};
|
||||
|
||||
/* 1.2.840.113549.1.12.10.1.3 */
|
||||
static const uint8_t kCertBag[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x0c, 0x0a, 0x01, 0x03};
|
||||
|
||||
/* 1.2.840.113549.1.9.22.1 */
|
||||
static const uint8_t kX509Certificate[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x09, 0x16, 0x01};
|
||||
|
||||
/* PKCS12_handle_safe_bag parses a single SafeBag element in a PKCS#12
|
||||
* structure. */
|
||||
static int PKCS12_handle_safe_bag(CBS *safe_bag, struct pkcs12_context *ctx) {
|
||||
CBS bag_id, wrapped_value;
|
||||
if (!CBS_get_asn1(safe_bag, &bag_id, CBS_ASN1_OBJECT) ||
|
||||
!CBS_get_asn1(safe_bag, &wrapped_value,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)
|
||||
/* Ignore the bagAttributes field. */) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CBS_mem_equal(&bag_id, kPKCS8ShroudedKeyBag,
|
||||
sizeof(kPKCS8ShroudedKeyBag))) {
|
||||
/* See RFC 7292, section 4.2.2. */
|
||||
if (*ctx->out_key) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_PKEY *pkey = PKCS8_parse_encrypted_private_key(
|
||||
&wrapped_value, ctx->password, ctx->password_len);
|
||||
if (pkey == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CBS_len(&wrapped_value) != 0) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
EVP_PKEY_free(pkey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ctx->out_key = pkey;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (CBS_mem_equal(&bag_id, kCertBag, sizeof(kCertBag))) {
|
||||
/* See RFC 7292, section 4.2.3. */
|
||||
CBS cert_bag, cert_type, wrapped_cert, cert;
|
||||
if (!CBS_get_asn1(&wrapped_value, &cert_bag, CBS_ASN1_SEQUENCE) ||
|
||||
!CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
|
||||
!CBS_get_asn1(&cert_bag, &wrapped_cert,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
|
||||
!CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip unknown certificate types. */
|
||||
if (!CBS_mem_equal(&cert_type, kX509Certificate,
|
||||
sizeof(kX509Certificate))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (CBS_len(&cert) > LONG_MAX) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t *inp = CBS_data(&cert);
|
||||
X509 *x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert));
|
||||
if (!x509) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (inp != CBS_data(&cert) + CBS_len(&cert)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
X509_free(x509);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == sk_X509_push(ctx->out_certs, x509)) {
|
||||
X509_free(x509);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Unknown element type - ignore it. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 1.2.840.113549.1.7.1 */
|
||||
static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x07, 0x01};
|
||||
|
||||
/* 1.2.840.113549.1.7.6 */
|
||||
static const uint8_t kPKCS7EncryptedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x07, 0x06};
|
||||
|
||||
/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
|
||||
* PKCS#12 structure. */
|
||||
static int PKCS12_handle_content_info(CBS *content_info,
|
||||
struct pkcs12_context *ctx) {
|
||||
CBS content_type, wrapped_contents, contents;
|
||||
int ret = 0;
|
||||
uint8_t *storage = NULL;
|
||||
|
||||
if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
|
||||
!CBS_get_asn1(content_info, &wrapped_contents,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
|
||||
CBS_len(content_info) != 0) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (CBS_mem_equal(&content_type, kPKCS7EncryptedData,
|
||||
sizeof(kPKCS7EncryptedData))) {
|
||||
/* See https://tools.ietf.org/html/rfc2315#section-13.
|
||||
*
|
||||
* PKCS#7 encrypted data inside a PKCS#12 structure is generally an
|
||||
* encrypted certificate bag and it's generally encrypted with 40-bit
|
||||
* RC2-CBC. */
|
||||
CBS version_bytes, eci, contents_type, ai, encrypted_contents;
|
||||
uint8_t *out;
|
||||
size_t out_len;
|
||||
|
||||
if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
|
||||
!CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
|
||||
/* EncryptedContentInfo, see
|
||||
* https://tools.ietf.org/html/rfc2315#section-10.1 */
|
||||
!CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
|
||||
!CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
|
||||
/* AlgorithmIdentifier, see
|
||||
* https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
|
||||
!CBS_get_asn1(&eci, &ai, CBS_ASN1_SEQUENCE) ||
|
||||
!CBS_get_asn1_implicit_string(
|
||||
&eci, &encrypted_contents, &storage,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | 0, CBS_ASN1_OCTETSTRING)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CBS_mem_equal(&contents_type, kPKCS7Data, sizeof(kPKCS7Data))) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!pkcs8_pbe_decrypt(&out, &out_len, &ai, ctx->password,
|
||||
ctx->password_len, CBS_data(&encrypted_contents),
|
||||
CBS_len(&encrypted_contents))) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS safe_contents;
|
||||
CBS_init(&safe_contents, out, out_len);
|
||||
ret = PKCS12_handle_sequence(&safe_contents, ctx, PKCS12_handle_safe_bag);
|
||||
OPENSSL_free(out);
|
||||
} else if (CBS_mem_equal(&content_type, kPKCS7Data, sizeof(kPKCS7Data))) {
|
||||
CBS octet_string_contents;
|
||||
|
||||
if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
|
||||
CBS_ASN1_OCTETSTRING)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = PKCS12_handle_sequence(&octet_string_contents, ctx,
|
||||
PKCS12_handle_safe_bag);
|
||||
} else {
|
||||
/* Unknown element type - ignore it. */
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
err:
|
||||
OPENSSL_free(storage);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
|
||||
CBS *ber_in, const char *password) {
|
||||
uint8_t *der_bytes = NULL;
|
||||
size_t der_len;
|
||||
CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes;
|
||||
uint64_t version;
|
||||
int ret = 0;
|
||||
struct pkcs12_context ctx;
|
||||
const size_t original_out_certs_len = sk_X509_num(out_certs);
|
||||
|
||||
/* The input may be in BER format. */
|
||||
if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
return 0;
|
||||
}
|
||||
if (der_bytes != NULL) {
|
||||
CBS_init(&in, der_bytes, der_len);
|
||||
} else {
|
||||
CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in));
|
||||
}
|
||||
|
||||
*out_key = NULL;
|
||||
OPENSSL_memset(&ctx, 0, sizeof(ctx));
|
||||
|
||||
/* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
|
||||
* four. */
|
||||
if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
|
||||
CBS_len(&in) != 0 ||
|
||||
!CBS_get_asn1_uint64(&pfx, &version)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (version < 3) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_VERSION);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (CBS_len(&pfx) == 0) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MISSING_MAC);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* authsafe is a PKCS#7 ContentInfo. See
|
||||
* https://tools.ietf.org/html/rfc2315#section-7. */
|
||||
if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) ||
|
||||
!CBS_get_asn1(&authsafe, &wrapped_authsafes,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* The content type can either be data or signedData. The latter indicates
|
||||
* that it's signed by a public key, which isn't supported. */
|
||||
if (!CBS_mem_equal(&content_type, kPKCS7Data, sizeof(kPKCS7Data))) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx.out_key = out_key;
|
||||
ctx.out_certs = out_certs;
|
||||
ctx.password = password;
|
||||
ctx.password_len = password != NULL ? strlen(password) : 0;
|
||||
|
||||
/* Verify the MAC. */
|
||||
{
|
||||
CBS mac, salt, expected_mac;
|
||||
if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
const EVP_MD *md = EVP_parse_digest_algorithm(&mac);
|
||||
if (md == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) ||
|
||||
!CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* The iteration count is optional and the default is one. */
|
||||
uint64_t iterations = 1;
|
||||
if (CBS_len(&mac_data) > 0) {
|
||||
if (!CBS_get_asn1_uint64(&mac_data, &iterations) ||
|
||||
iterations > UINT_MAX) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t hmac_key[EVP_MAX_MD_SIZE];
|
||||
if (!pkcs12_key_gen(ctx.password, ctx.password_len, CBS_data(&salt),
|
||||
CBS_len(&salt), PKCS12_MAC_ID, iterations,
|
||||
EVP_MD_size(md), hmac_key, md)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
uint8_t hmac[EVP_MAX_MD_SIZE];
|
||||
unsigned hmac_len;
|
||||
if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes),
|
||||
CBS_len(&authsafes), hmac, &hmac_len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INCORRECT_PASSWORD);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* authsafes contains a series of PKCS#7 ContentInfos. */
|
||||
if (!PKCS12_handle_sequence(&authsafes, &ctx, PKCS12_handle_content_info)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(der_bytes);
|
||||
if (!ret) {
|
||||
EVP_PKEY_free(*out_key);
|
||||
*out_key = NULL;
|
||||
while (sk_X509_num(out_certs) > original_out_certs_len) {
|
||||
X509 *x509 = sk_X509_pop(out_certs);
|
||||
X509_free(x509);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PKCS12_PBE_add(void) {}
|
||||
|
||||
struct pkcs12_st {
|
||||
uint8_t *ber_bytes;
|
||||
size_t ber_len;
|
||||
};
|
||||
|
||||
PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes,
|
||||
size_t ber_len) {
|
||||
PKCS12 *p12;
|
||||
|
||||
p12 = OPENSSL_malloc(sizeof(PKCS12));
|
||||
if (!p12) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p12->ber_bytes = OPENSSL_malloc(ber_len);
|
||||
if (!p12->ber_bytes) {
|
||||
OPENSSL_free(p12);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(p12->ber_bytes, *ber_bytes, ber_len);
|
||||
p12->ber_len = ber_len;
|
||||
*ber_bytes += ber_len;
|
||||
|
||||
if (out_p12) {
|
||||
PKCS12_free(*out_p12);
|
||||
|
||||
*out_p12 = p12;
|
||||
}
|
||||
|
||||
return p12;
|
||||
}
|
||||
|
||||
PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
|
||||
size_t used = 0;
|
||||
BUF_MEM *buf;
|
||||
const uint8_t *dummy;
|
||||
static const size_t kMaxSize = 256 * 1024;
|
||||
PKCS12 *ret = NULL;
|
||||
|
||||
buf = BUF_MEM_new();
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (BUF_MEM_grow(buf, 8192) == 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int n = BIO_read(bio, &buf->data[used], buf->length - used);
|
||||
if (n < 0) {
|
||||
if (used == 0) {
|
||||
goto out;
|
||||
}
|
||||
/* Workaround a bug in node.js. It uses a memory BIO for this in the wrong
|
||||
* mode. */
|
||||
n = 0;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
break;
|
||||
}
|
||||
used += n;
|
||||
|
||||
if (used < buf->length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf->length > kMaxSize ||
|
||||
BUF_MEM_grow(buf, buf->length * 2) == 0) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
dummy = (uint8_t*) buf->data;
|
||||
ret = d2i_PKCS12(out_p12, &dummy, used);
|
||||
|
||||
out:
|
||||
BUF_MEM_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) {
|
||||
BIO *bio;
|
||||
PKCS12 *ret;
|
||||
|
||||
bio = BIO_new_fp(fp, 0 /* don't take ownership */);
|
||||
if (!bio) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = d2i_PKCS12_bio(bio, out_p12);
|
||||
BIO_free(bio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
|
||||
X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
|
||||
CBS ber_bytes;
|
||||
STACK_OF(X509) *ca_certs = NULL;
|
||||
char ca_certs_alloced = 0;
|
||||
|
||||
if (out_ca_certs != NULL && *out_ca_certs != NULL) {
|
||||
ca_certs = *out_ca_certs;
|
||||
}
|
||||
|
||||
if (!ca_certs) {
|
||||
ca_certs = sk_X509_new_null();
|
||||
if (ca_certs == NULL) {
|
||||
OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
ca_certs_alloced = 1;
|
||||
}
|
||||
|
||||
CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len);
|
||||
if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) {
|
||||
if (ca_certs_alloced) {
|
||||
sk_X509_free(ca_certs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_cert = NULL;
|
||||
if (sk_X509_num(ca_certs) > 0) {
|
||||
*out_cert = sk_X509_shift(ca_certs);
|
||||
}
|
||||
|
||||
if (out_ca_certs) {
|
||||
*out_ca_certs = ca_certs;
|
||||
} else {
|
||||
sk_X509_pop_free(ca_certs, X509_free);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PKCS12_verify_mac(const PKCS12 *p12, const char *password,
|
||||
int password_len) {
|
||||
if (password == NULL) {
|
||||
if (password_len != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else if (password_len != -1 &&
|
||||
(password[password_len] != 0 ||
|
||||
OPENSSL_memchr(password, 0, password_len) != NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_PKEY *pkey = NULL;
|
||||
X509 *cert = NULL;
|
||||
if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) {
|
||||
ERR_clear_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(pkey);
|
||||
X509_free(cert);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PKCS12_free(PKCS12 *p12) {
|
||||
if (p12 == NULL) {
|
||||
return;
|
||||
}
|
||||
OPENSSL_free(p12->ber_bytes);
|
||||
OPENSSL_free(p12);
|
||||
}
|
||||
@@ -24,11 +24,11 @@
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occured.
|
||||
/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occurred.
|
||||
*
|
||||
* TODO(davidben): This is intentionally not thread-safe. If the fuzzer mode is
|
||||
* ever used in a multi-threaded program, replace this with a thread-local. (A
|
||||
* mutex would not be deterministic.) */
|
||||
* This is intentionally not thread-safe. If the fuzzer mode is ever used in a
|
||||
* multi-threaded program, replace this with a thread-local. (A mutex would not
|
||||
* be deterministic.) */
|
||||
static uint64_t g_num_calls = 0;
|
||||
|
||||
void RAND_reset_for_fuzzing(void) { g_num_calls = 0; }
|
||||
|
||||
+17
-18
@@ -95,24 +95,23 @@ int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx,
|
||||
BN_CTX *ctx);
|
||||
|
||||
|
||||
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len);
|
||||
int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len);
|
||||
int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len);
|
||||
int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len);
|
||||
int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len,
|
||||
const uint8_t *param, unsigned plen,
|
||||
const EVP_MD *md, const EVP_MD *mgf1md);
|
||||
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len,
|
||||
const uint8_t *param, unsigned plen,
|
||||
const EVP_MD *md, const EVP_MD *mgf1md);
|
||||
int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
|
||||
unsigned from_len);
|
||||
int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
|
||||
const uint8_t *from, size_t from_len);
|
||||
int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len,
|
||||
size_t max_out, const uint8_t *from,
|
||||
size_t from_len);
|
||||
int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
|
||||
const uint8_t *from, size_t from_len);
|
||||
int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
|
||||
size_t max_out, const uint8_t *from,
|
||||
size_t from_len);
|
||||
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
|
||||
size_t max_out, const uint8_t *from,
|
||||
size_t from_len, const uint8_t *param,
|
||||
size_t param_len, const EVP_MD *md,
|
||||
const EVP_MD *mgf1md);
|
||||
int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
|
||||
size_t from_len);
|
||||
|
||||
/* RSA_private_transform calls either the method-specific |private_transform|
|
||||
* function (if given) or the generic one. See the comment for
|
||||
|
||||
+158
-176
@@ -71,10 +71,9 @@
|
||||
|
||||
/* TODO(fork): don't the check functions have to be constant time? */
|
||||
|
||||
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len) {
|
||||
unsigned j;
|
||||
|
||||
int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
|
||||
const uint8_t *from, size_t from_len) {
|
||||
/* See RFC 8017, section 9.2. */
|
||||
if (to_len < RSA_PKCS1_PADDING_SIZE) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
@@ -85,118 +84,114 @@ int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *p = to;
|
||||
|
||||
*(p++) = 0;
|
||||
*(p++) = 1; /* Private Key BT (Block Type) */
|
||||
|
||||
/* pad out with 0xff data */
|
||||
j = to_len - 3 - from_len;
|
||||
OPENSSL_memset(p, 0xff, j);
|
||||
p += j;
|
||||
*(p++) = 0;
|
||||
OPENSSL_memcpy(p, from, from_len);
|
||||
to[0] = 0;
|
||||
to[1] = 1;
|
||||
OPENSSL_memset(to + 2, 0xff, to_len - 3 - from_len);
|
||||
to[to_len - from_len - 1] = 0;
|
||||
OPENSSL_memcpy(to + to_len - from_len, from, from_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len) {
|
||||
unsigned i, j;
|
||||
const uint8_t *p;
|
||||
|
||||
int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len,
|
||||
size_t max_out, const uint8_t *from,
|
||||
size_t from_len) {
|
||||
/* See RFC 8017, section 9.2. This is part of signature verification and thus
|
||||
* does not need to run in constant-time. */
|
||||
if (from_len < 2) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = from;
|
||||
if ((*(p++) != 0) || (*(p++) != 1)) {
|
||||
/* Check the header. */
|
||||
if (from[0] != 0 || from[1] != 1) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_BLOCK_TYPE_IS_NOT_01);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* scan over padding data */
|
||||
j = from_len - 2; /* one for leading 00, one for type. */
|
||||
for (i = 0; i < j; i++) {
|
||||
/* should decrypt to 0xff */
|
||||
if (*p != 0xff) {
|
||||
if (*p == 0) {
|
||||
p++;
|
||||
break;
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT);
|
||||
return -1;
|
||||
}
|
||||
/* Scan over padded data, looking for the 00. */
|
||||
size_t pad;
|
||||
for (pad = 2 /* header */; pad < from_len; pad++) {
|
||||
if (from[pad] == 0x00) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (from[pad] != 0xff) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (i == j) {
|
||||
if (pad == from_len) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i < 8) {
|
||||
if (pad < 2 /* header */ + 8) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_PAD_BYTE_COUNT);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
i++; /* Skip over the '\0' */
|
||||
j -= i;
|
||||
if (j > to_len) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
OPENSSL_memcpy(to, p, j);
|
||||
|
||||
return j;
|
||||
/* Skip over the 00. */
|
||||
pad++;
|
||||
|
||||
if (from_len - pad > max_out) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out, from + pad, from_len - pad);
|
||||
*out_len = from_len - pad;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len) {
|
||||
unsigned i, j;
|
||||
|
||||
if (to_len < RSA_PKCS1_PADDING_SIZE) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
static int rand_nonzero(uint8_t *out, size_t len) {
|
||||
if (!RAND_bytes(out, len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *p = to;
|
||||
|
||||
*(p++) = 0;
|
||||
*(p++) = 2; /* Public Key BT (Block Type) */
|
||||
|
||||
/* pad out with non-zero random data */
|
||||
j = to_len - 3 - from_len;
|
||||
|
||||
if (!RAND_bytes(p, j)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
while (*p == 0) {
|
||||
if (!RAND_bytes(p, 1)) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
while (out[i] == 0) {
|
||||
if (!RAND_bytes(out + i, 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
*(p++) = 0;
|
||||
|
||||
OPENSSL_memcpy(p, from, from_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len) {
|
||||
int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
|
||||
const uint8_t *from, size_t from_len) {
|
||||
/* See RFC 8017, section 7.2.1. */
|
||||
if (to_len < RSA_PKCS1_PADDING_SIZE) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
to[0] = 0;
|
||||
to[1] = 2;
|
||||
|
||||
size_t padding_len = to_len - 3 - from_len;
|
||||
if (!rand_nonzero(to + 2, padding_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
to[2 + padding_len] = 0;
|
||||
OPENSSL_memcpy(to + to_len - from_len, from, from_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
|
||||
size_t max_out, const uint8_t *from,
|
||||
size_t from_len) {
|
||||
if (from_len == 0) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
|
||||
@@ -205,29 +200,29 @@ int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
|
||||
/* |from| is zero-padded to the size of the RSA modulus, a public value, so
|
||||
* this can be rejected in non-constant time. */
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned first_byte_is_zero = constant_time_eq(from[0], 0);
|
||||
unsigned second_byte_is_two = constant_time_eq(from[1], 2);
|
||||
size_t first_byte_is_zero = constant_time_eq_s(from[0], 0);
|
||||
size_t second_byte_is_two = constant_time_eq_s(from[1], 2);
|
||||
|
||||
unsigned i, zero_index = 0, looking_for_index = ~0u;
|
||||
for (i = 2; i < from_len; i++) {
|
||||
unsigned equals0 = constant_time_is_zero(from[i]);
|
||||
zero_index = constant_time_select(looking_for_index & equals0, (unsigned)i,
|
||||
zero_index);
|
||||
looking_for_index = constant_time_select(equals0, 0, looking_for_index);
|
||||
size_t zero_index = 0, looking_for_index = CONSTTIME_TRUE_S;
|
||||
for (size_t i = 2; i < from_len; i++) {
|
||||
size_t equals0 = constant_time_is_zero_s(from[i]);
|
||||
zero_index =
|
||||
constant_time_select_s(looking_for_index & equals0, i, zero_index);
|
||||
looking_for_index = constant_time_select_s(equals0, 0, looking_for_index);
|
||||
}
|
||||
|
||||
/* The input must begin with 00 02. */
|
||||
unsigned valid_index = first_byte_is_zero;
|
||||
size_t valid_index = first_byte_is_zero;
|
||||
valid_index &= second_byte_is_two;
|
||||
|
||||
/* We must have found the end of PS. */
|
||||
valid_index &= ~looking_for_index;
|
||||
|
||||
/* PS must be at least 8 bytes long, and it starts two bytes into |from|. */
|
||||
valid_index &= constant_time_ge(zero_index, 2 + 8);
|
||||
valid_index &= constant_time_ge_s(zero_index, 2 + 8);
|
||||
|
||||
/* Skip the zero byte. */
|
||||
zero_index++;
|
||||
@@ -235,31 +230,28 @@ int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
|
||||
/* NOTE: Although this logic attempts to be constant time, the API contracts
|
||||
* of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it
|
||||
* impossible to completely avoid Bleichenbacher's attack. Consumers should
|
||||
* use |RSA_unpad_key_pkcs1|. */
|
||||
* use |RSA_PADDING_NONE| and perform the padding check in constant-time
|
||||
* combined with a swap to a random session key or other mitigation. */
|
||||
if (!valid_index) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned msg_len = from_len - zero_index;
|
||||
if (msg_len > to_len) {
|
||||
const size_t msg_len = from_len - zero_index;
|
||||
if (msg_len > max_out) {
|
||||
/* This shouldn't happen because this function is always called with
|
||||
* |to_len| as the key size and |from_len| is bounded by the key size. */
|
||||
* |max_out| as the key size and |from_len| is bounded by the key size. */
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg_len > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(to, &from[zero_index], msg_len);
|
||||
return (int)msg_len;
|
||||
OPENSSL_memcpy(out, &from[zero_index], msg_len);
|
||||
*out_len = msg_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
|
||||
unsigned from_len) {
|
||||
int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
|
||||
size_t from_len) {
|
||||
if (from_len > to_len) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return 0;
|
||||
@@ -317,15 +309,10 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len,
|
||||
const uint8_t *param, unsigned param_len,
|
||||
int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, size_t to_len,
|
||||
const uint8_t *from, size_t from_len,
|
||||
const uint8_t *param, size_t param_len,
|
||||
const EVP_MD *md, const EVP_MD *mgf1md) {
|
||||
unsigned i, emlen, mdlen;
|
||||
uint8_t *db, *seed;
|
||||
uint8_t *dbmask = NULL, seedmask[EVP_MAX_MD_SIZE];
|
||||
int ret = 0;
|
||||
|
||||
if (md == NULL) {
|
||||
md = EVP_sha1();
|
||||
}
|
||||
@@ -333,14 +320,14 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
mgf1md = md;
|
||||
}
|
||||
|
||||
mdlen = EVP_MD_size(md);
|
||||
size_t mdlen = EVP_MD_size(md);
|
||||
|
||||
if (to_len < 2 * mdlen + 2) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
emlen = to_len - 1;
|
||||
size_t emlen = to_len - 1;
|
||||
if (from_len > emlen - 2 * mdlen - 1) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return 0;
|
||||
@@ -352,8 +339,8 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
}
|
||||
|
||||
to[0] = 0;
|
||||
seed = to + 1;
|
||||
db = to + mdlen + 1;
|
||||
uint8_t *seed = to + 1;
|
||||
uint8_t *db = to + mdlen + 1;
|
||||
|
||||
if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) {
|
||||
return 0;
|
||||
@@ -365,23 +352,25 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbmask = OPENSSL_malloc(emlen - mdlen);
|
||||
uint8_t *dbmask = OPENSSL_malloc(emlen - mdlen);
|
||||
if (dbmask == NULL) {
|
||||
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
if (!PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md)) {
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < emlen - mdlen; i++) {
|
||||
for (size_t i = 0; i < emlen - mdlen; i++) {
|
||||
db[i] ^= dbmask[i];
|
||||
}
|
||||
|
||||
uint8_t seedmask[EVP_MAX_MD_SIZE];
|
||||
if (!PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md)) {
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < mdlen; i++) {
|
||||
for (size_t i = 0; i < mdlen; i++) {
|
||||
seed[i] ^= seedmask[i];
|
||||
}
|
||||
ret = 1;
|
||||
@@ -391,13 +380,12 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len,
|
||||
const uint8_t *param, unsigned param_len,
|
||||
const EVP_MD *md, const EVP_MD *mgf1md) {
|
||||
unsigned i, dblen, mlen = -1, mdlen, bad, looking_for_one_byte, one_index = 0;
|
||||
const uint8_t *maskeddb, *maskedseed;
|
||||
uint8_t *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
|
||||
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
|
||||
size_t max_out, const uint8_t *from,
|
||||
size_t from_len, const uint8_t *param,
|
||||
size_t param_len, const EVP_MD *md,
|
||||
const EVP_MD *mgf1md) {
|
||||
uint8_t *db = NULL;
|
||||
|
||||
if (md == NULL) {
|
||||
md = EVP_sha1();
|
||||
@@ -406,7 +394,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
mgf1md = md;
|
||||
}
|
||||
|
||||
mdlen = EVP_MD_size(md);
|
||||
size_t mdlen = EVP_MD_size(md);
|
||||
|
||||
/* The encoded message is one byte smaller than the modulus to ensure that it
|
||||
* doesn't end up greater than the modulus. Thus there's an extra "+1" here
|
||||
@@ -417,45 +405,47 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
goto decoding_err;
|
||||
}
|
||||
|
||||
dblen = from_len - mdlen - 1;
|
||||
size_t dblen = from_len - mdlen - 1;
|
||||
db = OPENSSL_malloc(dblen);
|
||||
if (db == NULL) {
|
||||
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
maskedseed = from + 1;
|
||||
maskeddb = from + 1 + mdlen;
|
||||
const uint8_t *maskedseed = from + 1;
|
||||
const uint8_t *maskeddb = from + 1 + mdlen;
|
||||
|
||||
uint8_t seed[EVP_MAX_MD_SIZE];
|
||||
if (!PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < mdlen; i++) {
|
||||
for (size_t i = 0; i < mdlen; i++) {
|
||||
seed[i] ^= maskedseed[i];
|
||||
}
|
||||
|
||||
if (!PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < dblen; i++) {
|
||||
for (size_t i = 0; i < dblen; i++) {
|
||||
db[i] ^= maskeddb[i];
|
||||
}
|
||||
|
||||
uint8_t phash[EVP_MAX_MD_SIZE];
|
||||
if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bad = ~constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));
|
||||
bad |= ~constant_time_is_zero(from[0]);
|
||||
size_t bad = ~constant_time_is_zero_s(CRYPTO_memcmp(db, phash, mdlen));
|
||||
bad |= ~constant_time_is_zero_s(from[0]);
|
||||
|
||||
looking_for_one_byte = ~0u;
|
||||
for (i = mdlen; i < dblen; i++) {
|
||||
unsigned equals1 = constant_time_eq(db[i], 1);
|
||||
unsigned equals0 = constant_time_eq(db[i], 0);
|
||||
one_index = constant_time_select(looking_for_one_byte & equals1, i,
|
||||
one_index);
|
||||
size_t looking_for_one_byte = CONSTTIME_TRUE_S, one_index = 0;
|
||||
for (size_t i = mdlen; i < dblen; i++) {
|
||||
size_t equals1 = constant_time_eq_s(db[i], 1);
|
||||
size_t equals0 = constant_time_eq_s(db[i], 0);
|
||||
one_index =
|
||||
constant_time_select_s(looking_for_one_byte & equals1, i, one_index);
|
||||
looking_for_one_byte =
|
||||
constant_time_select(equals1, 0, looking_for_one_byte);
|
||||
constant_time_select_s(equals1, 0, looking_for_one_byte);
|
||||
bad |= looking_for_one_byte & ~equals0;
|
||||
}
|
||||
|
||||
@@ -466,16 +456,16 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
|
||||
}
|
||||
|
||||
one_index++;
|
||||
mlen = dblen - one_index;
|
||||
if (to_len < mlen) {
|
||||
size_t mlen = dblen - one_index;
|
||||
if (max_out < mlen) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
|
||||
mlen = -1;
|
||||
} else {
|
||||
OPENSSL_memcpy(to, db + one_index, mlen);
|
||||
goto err;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out, db + one_index, mlen);
|
||||
*out_len = mlen;
|
||||
OPENSSL_free(db);
|
||||
return mlen;
|
||||
return 1;
|
||||
|
||||
decoding_err:
|
||||
/* to avoid chosen ciphertext attacks, the error message should not reveal
|
||||
@@ -483,10 +473,10 @@ decoding_err:
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_OAEP_DECODING_ERROR);
|
||||
err:
|
||||
OPENSSL_free(db);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0};
|
||||
static const uint8_t kPSSZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
|
||||
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
|
||||
@@ -530,7 +520,7 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
|
||||
EM++;
|
||||
emLen--;
|
||||
}
|
||||
if (emLen < ((int)hLen + sLen + 2)) {
|
||||
if (emLen < (int)hLen + 2 || emLen < ((int)hLen + sLen + 2)) {
|
||||
/* sLen can be small negative */
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
|
||||
goto err;
|
||||
@@ -567,16 +557,10 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
|
||||
!EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
|
||||
!EVP_DigestUpdate(&ctx, mHash, hLen)) {
|
||||
goto err;
|
||||
}
|
||||
if (maskedDBLen - i) {
|
||||
if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (!EVP_DigestFinal_ex(&ctx, H_, NULL)) {
|
||||
!EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) ||
|
||||
!EVP_DigestUpdate(&ctx, mHash, hLen) ||
|
||||
!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i) ||
|
||||
!EVP_DigestFinal_ex(&ctx, H_, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
if (OPENSSL_memcmp(H_, H, hLen)) {
|
||||
@@ -601,7 +585,6 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
|
||||
size_t maskedDBLen, MSBits, emLen;
|
||||
size_t hLen;
|
||||
unsigned char *H, *salt = NULL, *p;
|
||||
EVP_MD_CTX ctx;
|
||||
|
||||
if (mgf1Hash == NULL) {
|
||||
mgf1Hash = Hash;
|
||||
@@ -660,19 +643,18 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
|
||||
}
|
||||
maskedDBLen = emLen - hLen - 1;
|
||||
H = EM + maskedDBLen;
|
||||
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
|
||||
!EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
|
||||
!EVP_DigestUpdate(&ctx, mHash, hLen)) {
|
||||
goto err;
|
||||
}
|
||||
if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen)) {
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_DigestFinal_ex(&ctx, H, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
int digest_ok = EVP_DigestInit_ex(&ctx, Hash, NULL) &&
|
||||
EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) &&
|
||||
EVP_DigestUpdate(&ctx, mHash, hLen) &&
|
||||
EVP_DigestUpdate(&ctx, salt, sLen) &&
|
||||
EVP_DigestFinal_ex(&ctx, H, NULL);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
if (!digest_ok) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Generate dbMask in place then perform XOR on it */
|
||||
if (!PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) {
|
||||
|
||||
@@ -321,13 +321,6 @@ int RSA_is_opaque(const RSA *rsa) {
|
||||
return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE);
|
||||
}
|
||||
|
||||
int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
|
||||
if (rsa->meth && rsa->meth->supports_digest) {
|
||||
return rsa->meth->supports_digest(rsa, md);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
|
||||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
|
||||
int index;
|
||||
|
||||
+13
-16
@@ -363,7 +363,6 @@ err:
|
||||
int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
|
||||
const uint8_t *in, size_t in_len, int padding) {
|
||||
const unsigned rsa_size = RSA_size(rsa);
|
||||
int r = -1;
|
||||
uint8_t *buf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
@@ -394,26 +393,25 @@ int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_2(out, rsa_size, buf, rsa_size);
|
||||
ret =
|
||||
RSA_padding_check_PKCS1_type_2(out, out_len, rsa_size, buf, rsa_size);
|
||||
break;
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
/* Use the default parameters: SHA-1 for both hashes and no label. */
|
||||
r = RSA_padding_check_PKCS1_OAEP_mgf1(out, rsa_size, buf, rsa_size,
|
||||
NULL, 0, NULL, NULL);
|
||||
ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, out_len, rsa_size, buf,
|
||||
rsa_size, NULL, 0, NULL, NULL);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = rsa_size;
|
||||
*out_len = rsa_size;
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if (!ret) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
|
||||
} else {
|
||||
*out_len = r;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
err:
|
||||
@@ -436,7 +434,6 @@ int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
|
||||
|
||||
const unsigned rsa_size = RSA_size(rsa);
|
||||
BIGNUM *f, *result;
|
||||
int r = -1;
|
||||
|
||||
if (max_out < rsa_size) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
@@ -500,21 +497,21 @@ int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_1(out, rsa_size, buf, rsa_size);
|
||||
ret =
|
||||
RSA_padding_check_PKCS1_type_1(out, out_len, rsa_size, buf, rsa_size);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = rsa_size;
|
||||
ret = 1;
|
||||
*out_len = rsa_size;
|
||||
break;
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if (!ret) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
|
||||
} else {
|
||||
*out_len = r;
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
|
||||
@@ -105,7 +105,9 @@ static const vec_uint32_t K_60_79_x_4 = {K_60_79, K_60_79, K_60_79, K_60_79};
|
||||
* Byte shifting code below may not be correct for big-endian systems. */
|
||||
static vec_uint32_t sched_00_15(vec_uint32_t *pre_added, const void *data,
|
||||
vec_uint32_t k) {
|
||||
const vec_uint32_t v = *((const vec_uint32_t *)data);
|
||||
const vector unsigned char unaligned_data =
|
||||
vec_vsx_ld(0, (const unsigned char*) data);
|
||||
const vec_uint32_t v = (vec_uint32_t) unaligned_data;
|
||||
const vec_uint32_t w = vec_perm(v, v, k_swap_endianness);
|
||||
vec_st(w + k, 0, pre_added);
|
||||
return w;
|
||||
|
||||
@@ -82,12 +82,6 @@ int SHA1_Init(SHA_CTX *sha) {
|
||||
|
||||
uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
SHA_CTX ctx;
|
||||
static uint8_t buf[SHA_DIGEST_LENGTH];
|
||||
|
||||
/* TODO(fork): remove this static buffer. */
|
||||
if (out == NULL) {
|
||||
out = buf;
|
||||
}
|
||||
if (!SHA1_Init(&ctx)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -99,12 +99,6 @@ int SHA256_Init(SHA256_CTX *sha) {
|
||||
|
||||
uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
SHA256_CTX ctx;
|
||||
static uint8_t buf[SHA224_DIGEST_LENGTH];
|
||||
|
||||
/* TODO(fork): remove this static buffer. */
|
||||
if (out == NULL) {
|
||||
out = buf;
|
||||
}
|
||||
SHA224_Init(&ctx);
|
||||
SHA224_Update(&ctx, data, len);
|
||||
SHA224_Final(out, &ctx);
|
||||
@@ -114,12 +108,6 @@ uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
|
||||
uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
SHA256_CTX ctx;
|
||||
static uint8_t buf[SHA256_DIGEST_LENGTH];
|
||||
|
||||
/* TODO(fork): remove this static buffer. */
|
||||
if (out == NULL) {
|
||||
out = buf;
|
||||
}
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, data, len);
|
||||
SHA256_Final(out, &ctx);
|
||||
|
||||
@@ -123,13 +123,6 @@ int SHA512_Init(SHA512_CTX *sha) {
|
||||
|
||||
uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
SHA512_CTX ctx;
|
||||
static uint8_t buf[SHA384_DIGEST_LENGTH];
|
||||
|
||||
/* TODO(fork): remove this static buffer. */
|
||||
if (out == NULL) {
|
||||
out = buf;
|
||||
}
|
||||
|
||||
SHA384_Init(&ctx);
|
||||
SHA384_Update(&ctx, data, len);
|
||||
SHA384_Final(out, &ctx);
|
||||
@@ -139,12 +132,6 @@ uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
|
||||
uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out) {
|
||||
SHA512_CTX ctx;
|
||||
static uint8_t buf[SHA512_DIGEST_LENGTH];
|
||||
|
||||
/* TODO(fork): remove this static buffer. */
|
||||
if (out == NULL) {
|
||||
out = buf;
|
||||
}
|
||||
SHA512_Init(&ctx);
|
||||
SHA512_Update(&ctx, data, len);
|
||||
SHA512_Final(out, &ctx);
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class ErrorTestEventListener : public testing::EmptyTestEventListener {
|
||||
@@ -41,6 +48,22 @@ class ErrorTestEventListener : public testing::EmptyTestEventListener {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// Initialize Winsock.
|
||||
WORD wsa_version = MAKEWORD(2, 2);
|
||||
WSADATA wsa_data;
|
||||
int wsa_err = WSAStartup(wsa_version, &wsa_data);
|
||||
if (wsa_err != 0) {
|
||||
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
|
||||
return 1;
|
||||
}
|
||||
if (wsa_data.wVersion != wsa_version) {
|
||||
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
testing::UnitTest::GetInstance()->listeners().Append(
|
||||
new ErrorTestEventListener);
|
||||
|
||||
@@ -34,6 +34,8 @@ void hexdump(FILE *fp, const char *msg, const void *in, size_t len);
|
||||
struct Bytes {
|
||||
Bytes(const uint8_t *data_arg, size_t len_arg)
|
||||
: data(data_arg), len(len_arg) {}
|
||||
Bytes(const char *data_arg, size_t len_arg)
|
||||
: data(reinterpret_cast<const uint8_t *>(data_arg)), len(len_arg) {}
|
||||
|
||||
Bytes(const char *str)
|
||||
: data(reinterpret_cast<const uint8_t *>(str)), len(strlen(str)) {}
|
||||
|
||||
+19
-15
@@ -27,6 +27,14 @@
|
||||
#include "../bytestring/internal.h"
|
||||
|
||||
|
||||
/* 1.2.840.113549.1.7.1 */
|
||||
static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x07, 0x01};
|
||||
|
||||
/* 1.2.840.113549.1.7.2 */
|
||||
static const uint8_t kPKCS7SignedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x07, 0x02};
|
||||
|
||||
/* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7
|
||||
* SignedData blob from |cbs| and sets |*out| to point to the rest of the
|
||||
* input. If the input is in BER format, then |*der_bytes| will be set to a
|
||||
@@ -57,7 +65,8 @@ static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
|
||||
if (!CBS_mem_equal(&content_type, kPKCS7SignedData,
|
||||
sizeof(kPKCS7SignedData))) {
|
||||
OPENSSL_PUT_ERROR(X509, X509_R_NOT_PKCS7_SIGNED_DATA);
|
||||
goto err;
|
||||
}
|
||||
@@ -81,11 +90,8 @@ static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) {
|
||||
return 1;
|
||||
|
||||
err:
|
||||
if (*der_bytes) {
|
||||
OPENSSL_free(*der_bytes);
|
||||
*der_bytes = NULL;
|
||||
}
|
||||
|
||||
OPENSSL_free(*der_bytes);
|
||||
*der_bytes = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -135,9 +141,7 @@ int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (der_bytes) {
|
||||
OPENSSL_free(der_bytes);
|
||||
}
|
||||
OPENSSL_free(der_bytes);
|
||||
|
||||
if (!ret) {
|
||||
while (sk_X509_num(out_certs) != initial_certs_len) {
|
||||
@@ -205,9 +209,7 @@ int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) {
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (der_bytes) {
|
||||
OPENSSL_free(der_bytes);
|
||||
}
|
||||
OPENSSL_free(der_bytes);
|
||||
|
||||
if (!ret) {
|
||||
while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
|
||||
@@ -270,12 +272,13 @@ int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) {
|
||||
* pkcs7_bundle returns one on success or zero on error. */
|
||||
static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg),
|
||||
const void *arg) {
|
||||
CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set,
|
||||
CBB outer_seq, oid, wrapped_seq, seq, version_bytes, digest_algos_set,
|
||||
content_info;
|
||||
|
||||
/* See https://tools.ietf.org/html/rfc2315#section-7 */
|
||||
if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
|
||||
!OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
|
||||
!CBB_add_asn1(&outer_seq, &oid, CBS_ASN1_OBJECT) ||
|
||||
!CBB_add_bytes(&oid, kPKCS7SignedData, sizeof(kPKCS7SignedData)) ||
|
||||
!CBB_add_asn1(&outer_seq, &wrapped_seq,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
|
||||
/* See https://tools.ietf.org/html/rfc2315#section-9.1 */
|
||||
@@ -284,7 +287,8 @@ static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg),
|
||||
!CBB_add_u8(&version_bytes, 1) ||
|
||||
!CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
|
||||
!CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
|
||||
!OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
|
||||
!CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) ||
|
||||
!CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
|
||||
!cb(&seq, arg)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+12
-4
@@ -356,8 +356,12 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
|
||||
OPENSSL_free(obj);
|
||||
OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
|
||||
ret = 0;
|
||||
} else
|
||||
sk_X509_OBJECT_push(ctx->objs, obj);
|
||||
} else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
|
||||
X509_OBJECT_free_contents(obj);
|
||||
OPENSSL_free(obj);
|
||||
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
|
||||
|
||||
@@ -388,8 +392,12 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
|
||||
OPENSSL_free(obj);
|
||||
OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
|
||||
ret = 0;
|
||||
} else
|
||||
sk_X509_OBJECT_push(ctx->objs, obj);
|
||||
} else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
|
||||
X509_OBJECT_free_contents(obj);
|
||||
OPENSSL_free(obj);
|
||||
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
|
||||
|
||||
|
||||
@@ -468,9 +468,15 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent)
|
||||
num = sk_ASN1_INTEGER_value(ref->noticenos, i);
|
||||
if (i)
|
||||
BIO_puts(out, ", ");
|
||||
tmp = i2s_ASN1_INTEGER(NULL, num);
|
||||
BIO_puts(out, tmp);
|
||||
OPENSSL_free(tmp);
|
||||
if (num == NULL)
|
||||
BIO_puts(out, "(null)");
|
||||
else {
|
||||
tmp = i2s_ASN1_INTEGER(NULL, num);
|
||||
if (tmp == NULL)
|
||||
return;
|
||||
BIO_puts(out, tmp);
|
||||
OPENSSL_free(tmp);
|
||||
}
|
||||
}
|
||||
BIO_puts(out, "\n");
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/conf.h>
|
||||
@@ -153,38 +152,6 @@ static int process_pci_value(CONF_VALUE *val,
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(tmp_data2);
|
||||
} else if (strncmp(val->value, "file:", 5) == 0) {
|
||||
unsigned char buf[2048];
|
||||
int n;
|
||||
BIO *b = BIO_new_file(val->value + 5, "r");
|
||||
if (!b) {
|
||||
OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
|
||||
X509V3_conf_err(val);
|
||||
goto err;
|
||||
}
|
||||
while ((n = BIO_read(b, buf, sizeof(buf))) > 0
|
||||
|| (n == 0 && BIO_should_retry(b))) {
|
||||
if (!n)
|
||||
continue;
|
||||
|
||||
tmp_data = OPENSSL_realloc((*policy)->data,
|
||||
(*policy)->length + n + 1);
|
||||
|
||||
if (!tmp_data)
|
||||
break;
|
||||
|
||||
(*policy)->data = tmp_data;
|
||||
OPENSSL_memcpy(&(*policy)->data[(*policy)->length], buf, n);
|
||||
(*policy)->length += n;
|
||||
(*policy)->data[(*policy)->length] = '\0';
|
||||
}
|
||||
BIO_free_all(b);
|
||||
|
||||
if (n < 0) {
|
||||
OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
|
||||
X509V3_conf_err(val);
|
||||
goto err;
|
||||
}
|
||||
} else if (strncmp(val->value, "text:", 5) == 0) {
|
||||
val_len = strlen(val->value + 5);
|
||||
tmp_data = OPENSSL_realloc((*policy)->data,
|
||||
|
||||
@@ -46,4 +46,7 @@ add_executable(
|
||||
)
|
||||
|
||||
target_link_libraries(decrepit_test crypto decrepit gtest)
|
||||
if (WIN32)
|
||||
target_link_libraries(decrepit_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests decrepit_test)
|
||||
|
||||
@@ -95,9 +95,9 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, const EVP_MD *Hash,
|
||||
return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
|
||||
}
|
||||
|
||||
int RSA_padding_add_PKCS1_OAEP(uint8_t *to, unsigned to_len,
|
||||
const uint8_t *from, unsigned from_len,
|
||||
const uint8_t *param, unsigned param_len) {
|
||||
int RSA_padding_add_PKCS1_OAEP(uint8_t *to, size_t to_len,
|
||||
const uint8_t *from, size_t from_len,
|
||||
const uint8_t *param, size_t param_len) {
|
||||
return RSA_padding_add_PKCS1_OAEP_mgf1(to, to_len, from, from_len, param,
|
||||
param_len, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -247,8 +247,6 @@ struct GlobalState {
|
||||
assert(pkey != nullptr);
|
||||
SSL_CTX_set1_tls_channel_id(ctx, pkey);
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
SSL_CTX_set_short_header_enabled(ctx, 1);
|
||||
}
|
||||
|
||||
~GlobalState() {
|
||||
|
||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user