/programs/develop/libraries/kos_mbedtls/library/.gitignore |
---|
0,0 → 1,0 |
*.o |
/programs/develop/libraries/kos_mbedtls/library/CMakeLists.txt |
---|
0,0 → 1,187 |
option(USE_STATIC_MBEDTLS_LIBRARY "Build mbed TLS static library." ON) |
option(USE_SHARED_MBEDTLS_LIBRARY "Build mbed TLS shared library." OFF) |
option(LINK_WITH_PTHREAD "Explicitly link mbed TLS library to pthread." OFF) |
set(src_crypto |
aes.c |
aesni.c |
arc4.c |
aria.c |
asn1parse.c |
asn1write.c |
base64.c |
bignum.c |
blowfish.c |
camellia.c |
ccm.c |
chacha20.c |
chachapoly.c |
cipher.c |
cipher_wrap.c |
cmac.c |
ctr_drbg.c |
des.c |
dhm.c |
ecdh.c |
ecdsa.c |
ecjpake.c |
ecp.c |
ecp_curves.c |
entropy.c |
entropy_poll.c |
error.c |
gcm.c |
havege.c |
hkdf.c |
hmac_drbg.c |
md.c |
md2.c |
md4.c |
md5.c |
md_wrap.c |
memory_buffer_alloc.c |
nist_kw.c |
oid.c |
padlock.c |
pem.c |
pk.c |
pk_wrap.c |
pkcs12.c |
pkcs5.c |
pkparse.c |
pkwrite.c |
platform.c |
platform_util.c |
poly1305.c |
ripemd160.c |
rsa.c |
rsa_internal.c |
sha1.c |
sha256.c |
sha512.c |
threading.c |
timing.c |
version.c |
version_features.c |
xtea.c |
) |
set(src_x509 |
certs.c |
pkcs11.c |
x509.c |
x509_create.c |
x509_crl.c |
x509_crt.c |
x509_csr.c |
x509write_crt.c |
x509write_csr.c |
) |
set(src_tls |
debug.c |
net_sockets.c |
ssl_cache.c |
ssl_ciphersuites.c |
ssl_cli.c |
ssl_cookie.c |
ssl_srv.c |
ssl_ticket.c |
ssl_tls.c |
) |
if(CMAKE_COMPILER_IS_GNUCC) |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes") |
endif(CMAKE_COMPILER_IS_GNUCC) |
if(CMAKE_COMPILER_IS_CLANG) |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") |
endif(CMAKE_COMPILER_IS_CLANG) |
if(UNSAFE_BUILD) |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error") |
set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} -Wno-error") |
set(CMAKE_C_FLAGS_ASANDBG "${CMAKE_C_FLAGS_ASANDBG} -Wno-error") |
endif(UNSAFE_BUILD) |
if(WIN32) |
set(libs ${libs} ws2_32) |
endif(WIN32) |
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") |
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>") |
SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>") |
SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>") |
SET(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>") |
endif() |
if(HAIKU) |
set(libs ${libs} network) |
endif(HAIKU) |
if(USE_PKCS11_HELPER_LIBRARY) |
set(libs ${libs} pkcs11-helper) |
endif(USE_PKCS11_HELPER_LIBRARY) |
if(ENABLE_ZLIB_SUPPORT) |
set(libs ${libs} ${ZLIB_LIBRARIES}) |
endif(ENABLE_ZLIB_SUPPORT) |
if(LINK_WITH_PTHREAD) |
set(libs ${libs} pthread) |
endif() |
if (NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) |
message(FATAL_ERROR "Need to choose static or shared mbedtls build!") |
endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) |
if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) |
set(mbedtls_static_target "mbedtls_static") |
set(mbedx509_static_target "mbedx509_static") |
set(mbedcrypto_static_target "mbedcrypto_static") |
elseif(USE_STATIC_MBEDTLS_LIBRARY) |
set(mbedtls_static_target "mbedtls") |
set(mbedx509_static_target "mbedx509") |
set(mbedcrypto_static_target "mbedcrypto") |
endif() |
if(USE_STATIC_MBEDTLS_LIBRARY) |
add_library(${mbedcrypto_static_target} STATIC ${src_crypto}) |
set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto) |
target_link_libraries(${mbedcrypto_static_target} ${libs}) |
add_library(${mbedx509_static_target} STATIC ${src_x509}) |
set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509) |
target_link_libraries(${mbedx509_static_target} ${libs} ${mbedcrypto_static_target}) |
add_library(${mbedtls_static_target} STATIC ${src_tls}) |
set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls) |
target_link_libraries(${mbedtls_static_target} ${libs} ${mbedx509_static_target}) |
install(TARGETS ${mbedtls_static_target} ${mbedx509_static_target} ${mbedcrypto_static_target} |
DESTINATION ${LIB_INSTALL_DIR} |
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) |
endif(USE_STATIC_MBEDTLS_LIBRARY) |
if(USE_SHARED_MBEDTLS_LIBRARY) |
add_library(mbedcrypto SHARED ${src_crypto}) |
set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.6 SOVERSION 3) |
target_link_libraries(mbedcrypto ${libs}) |
add_library(mbedx509 SHARED ${src_x509}) |
set_target_properties(mbedx509 PROPERTIES VERSION 2.16.6 SOVERSION 0) |
target_link_libraries(mbedx509 ${libs} mbedcrypto) |
add_library(mbedtls SHARED ${src_tls}) |
set_target_properties(mbedtls PROPERTIES VERSION 2.16.6 SOVERSION 12) |
target_link_libraries(mbedtls ${libs} mbedx509) |
install(TARGETS mbedtls mbedx509 mbedcrypto |
DESTINATION ${LIB_INSTALL_DIR} |
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) |
endif(USE_SHARED_MBEDTLS_LIBRARY) |
add_custom_target(lib DEPENDS mbedcrypto mbedx509 mbedtls) |
if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) |
add_dependencies(lib mbedcrypto_static mbedx509_static mbedtls_static) |
endif() |
/programs/develop/libraries/kos_mbedtls/library/Makefile |
---|
0,0 → 1,92 |
# Also see "include/mbedtls/config.h" |
NEWLIB_INCLUDES=D:\KOSSDK\newlib\libc\include |
KOSNET_INCLUDES=../kosnet/include |
CC = kos32-gcc |
AR = kos32-ar |
CFLAGS ?= -O2 |
WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement |
LDFLAGS ?= |
LOCAL_CFLAGS = $(WARNING_CFLAGS) -I $(NEWLIB_INCLUDES) -I../include -I $(KOSNET_INCLUDES) -D_FILE_OFFSET_BITS=64 |
LOCAL_LDFLAGS = |
ifdef DEBUG |
LOCAL_CFLAGS += -g3 |
endif |
# Set AR_DASH= (empty string) to use an ar implementation that does not accept |
# the - prefix for command line options (e.g. llvm-ar) |
AR_DASH ?= - |
ARFLAGS = $(AR_DASH)src |
OBJS_CRYPTO= aes.o aesni.o arc4.o \ |
aria.o asn1parse.o asn1write.o \ |
base64.o bignum.o blowfish.o \ |
camellia.o ccm.o chacha20.o \ |
chachapoly.o cipher.o cipher_wrap.o \ |
cmac.o ctr_drbg.o des.o \ |
dhm.o ecdh.o ecdsa.o \ |
ecjpake.o ecp.o \ |
ecp_curves.o entropy.o entropy_poll.o \ |
error.o gcm.o havege.o \ |
hkdf.o \ |
hmac_drbg.o md.o md2.o \ |
md4.o md5.o md_wrap.o \ |
memory_buffer_alloc.o nist_kw.o \ |
oid.o padlock.o pem.o \ |
pk.o pk_wrap.o pkcs12.o \ |
pkcs5.o pkparse.o pkwrite.o \ |
platform.o platform_util.o poly1305.o \ |
ripemd160.o rsa_internal.o rsa.o \ |
sha1.o sha256.o sha512.o \ |
threading.o timing.o version.o \ |
version_features.o xtea.o |
OBJS_X509= certs.o pkcs11.o x509.o \ |
x509_create.o x509_crl.o x509_crt.o \ |
x509_csr.o x509write_crt.o x509write_csr.o |
OBJS_TLS= debug.o net_sockets.o \ |
ssl_cache.o ssl_ciphersuites.o \ |
ssl_cli.o ssl_cookie.o \ |
ssl_srv.o ssl_ticket.o \ |
ssl_tls.o |
.SILENT: |
.PHONY: all static clean |
all: static |
static: libmbedcrypto.a libmbedx509.a libmbedtls.a |
# tls |
libmbedtls.a: $(OBJS_TLS) |
echo " AR $@" |
$(AR) $(ARFLAGS) $@ $(OBJS_TLS) |
# x509 |
libmbedx509.a: $(OBJS_X509) |
echo " AR $@" |
$(AR) $(ARFLAGS) $@ $(OBJS_X509) |
# crypto |
libmbedcrypto.a: $(OBJS_CRYPTO) |
echo " AR $@" |
$(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO) |
.c.o: |
echo " CC $<" |
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $< |
clean: |
ifndef WINDOWS |
rm -f *.o libmbed* |
else |
del /Q /F *.o libmbed* |
endif |
/programs/develop/libraries/kos_mbedtls/library/aes.c |
---|
0,0 → 1,2235 |
/* |
* FIPS-197 compliant AES implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen. |
* |
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf |
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_AES_C) |
#include <string.h> |
#include "mbedtls/aes.h" |
#include "mbedtls/platform.h" |
#include "mbedtls/platform_util.h" |
#if defined(MBEDTLS_PADLOCK_C) |
#include "mbedtls/padlock.h" |
#endif |
#if defined(MBEDTLS_AESNI_C) |
#include "mbedtls/aesni.h" |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_AES_ALT) |
/* Parameter validation macros based on platform_util.h */ |
#define AES_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) |
#define AES_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* 32-bit integer manipulation macros (little endian) |
*/ |
#ifndef GET_UINT32_LE |
#define GET_UINT32_LE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] ) \ |
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 3] << 24 ); \ |
} |
#endif |
#ifndef PUT_UINT32_LE |
#define PUT_UINT32_LE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ |
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ |
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ |
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ |
} |
#endif |
#if defined(MBEDTLS_PADLOCK_C) && \ |
( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) |
static int aes_padlock_ace = -1; |
#endif |
#if defined(MBEDTLS_AES_ROM_TABLES) |
/* |
* Forward S-box |
*/ |
static const unsigned char FSb[256] = |
{ |
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, |
0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, |
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, |
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, |
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, |
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, |
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, |
0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, |
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, |
0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, |
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, |
0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, |
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, |
0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, |
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, |
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, |
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, |
0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, |
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, |
0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, |
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, |
0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, |
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, |
0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, |
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, |
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, |
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, |
0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, |
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, |
0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, |
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, |
0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 |
}; |
/* |
* Forward tables |
*/ |
#define FT \ |
\ |
V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ |
V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ |
V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ |
V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ |
V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ |
V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ |
V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ |
V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ |
V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ |
V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ |
V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ |
V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ |
V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ |
V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ |
V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ |
V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ |
V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ |
V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ |
V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ |
V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ |
V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ |
V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ |
V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ |
V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ |
V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ |
V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ |
V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ |
V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ |
V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ |
V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ |
V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ |
V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ |
V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ |
V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ |
V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ |
V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ |
V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ |
V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ |
V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ |
V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ |
V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ |
V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ |
V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ |
V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ |
V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ |
V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ |
V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ |
V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ |
V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ |
V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ |
V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ |
V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ |
V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ |
V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ |
V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ |
V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ |
V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ |
V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ |
V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ |
V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ |
V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ |
V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ |
V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ |
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) |
#define V(a,b,c,d) 0x##a##b##c##d |
static const uint32_t FT0[256] = { FT }; |
#undef V |
#if !defined(MBEDTLS_AES_FEWER_TABLES) |
#define V(a,b,c,d) 0x##b##c##d##a |
static const uint32_t FT1[256] = { FT }; |
#undef V |
#define V(a,b,c,d) 0x##c##d##a##b |
static const uint32_t FT2[256] = { FT }; |
#undef V |
#define V(a,b,c,d) 0x##d##a##b##c |
static const uint32_t FT3[256] = { FT }; |
#undef V |
#endif /* !MBEDTLS_AES_FEWER_TABLES */ |
#undef FT |
/* |
* Reverse S-box |
*/ |
static const unsigned char RSb[256] = |
{ |
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, |
0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, |
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, |
0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, |
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, |
0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, |
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, |
0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, |
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, |
0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, |
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, |
0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, |
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, |
0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, |
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, |
0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, |
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, |
0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, |
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, |
0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, |
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, |
0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, |
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, |
0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, |
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, |
0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, |
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, |
0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, |
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, |
0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, |
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, |
0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D |
}; |
/* |
* Reverse tables |
*/ |
#define RT \ |
\ |
V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ |
V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ |
V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ |
V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ |
V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ |
V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ |
V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ |
V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ |
V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ |
V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ |
V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ |
V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ |
V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ |
V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ |
V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ |
V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ |
V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ |
V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ |
V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ |
V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ |
V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ |
V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ |
V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ |
V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ |
V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ |
V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ |
V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ |
V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ |
V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ |
V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ |
V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ |
V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ |
V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ |
V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ |
V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ |
V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ |
V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ |
V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ |
V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ |
V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ |
V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ |
V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ |
V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ |
V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ |
V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ |
V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ |
V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ |
V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ |
V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ |
V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ |
V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ |
V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ |
V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ |
V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ |
V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ |
V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ |
V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ |
V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ |
V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ |
V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ |
V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ |
V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ |
V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ |
V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) |
#define V(a,b,c,d) 0x##a##b##c##d |
static const uint32_t RT0[256] = { RT }; |
#undef V |
#if !defined(MBEDTLS_AES_FEWER_TABLES) |
#define V(a,b,c,d) 0x##b##c##d##a |
static const uint32_t RT1[256] = { RT }; |
#undef V |
#define V(a,b,c,d) 0x##c##d##a##b |
static const uint32_t RT2[256] = { RT }; |
#undef V |
#define V(a,b,c,d) 0x##d##a##b##c |
static const uint32_t RT3[256] = { RT }; |
#undef V |
#endif /* !MBEDTLS_AES_FEWER_TABLES */ |
#undef RT |
/* |
* Round constants |
*/ |
static const uint32_t RCON[10] = |
{ |
0x00000001, 0x00000002, 0x00000004, 0x00000008, |
0x00000010, 0x00000020, 0x00000040, 0x00000080, |
0x0000001B, 0x00000036 |
}; |
#else /* MBEDTLS_AES_ROM_TABLES */ |
/* |
* Forward S-box & tables |
*/ |
static unsigned char FSb[256]; |
static uint32_t FT0[256]; |
#if !defined(MBEDTLS_AES_FEWER_TABLES) |
static uint32_t FT1[256]; |
static uint32_t FT2[256]; |
static uint32_t FT3[256]; |
#endif /* !MBEDTLS_AES_FEWER_TABLES */ |
/* |
* Reverse S-box & tables |
*/ |
static unsigned char RSb[256]; |
static uint32_t RT0[256]; |
#if !defined(MBEDTLS_AES_FEWER_TABLES) |
static uint32_t RT1[256]; |
static uint32_t RT2[256]; |
static uint32_t RT3[256]; |
#endif /* !MBEDTLS_AES_FEWER_TABLES */ |
/* |
* Round constants |
*/ |
static uint32_t RCON[10]; |
/* |
* Tables generation code |
*/ |
#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 ) |
#define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) ) |
#define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 ) |
static int aes_init_done = 0; |
static void aes_gen_tables( void ) |
{ |
int i, x, y, z; |
int pow[256]; |
int log[256]; |
/* |
* compute pow and log tables over GF(2^8) |
*/ |
for( i = 0, x = 1; i < 256; i++ ) |
{ |
pow[i] = x; |
log[x] = i; |
x = ( x ^ XTIME( x ) ) & 0xFF; |
} |
/* |
* calculate the round constants |
*/ |
for( i = 0, x = 1; i < 10; i++ ) |
{ |
RCON[i] = (uint32_t) x; |
x = XTIME( x ) & 0xFF; |
} |
/* |
* generate the forward and reverse S-boxes |
*/ |
FSb[0x00] = 0x63; |
RSb[0x63] = 0x00; |
for( i = 1; i < 256; i++ ) |
{ |
x = pow[255 - log[i]]; |
y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; |
x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; |
x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; |
x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; |
x ^= y ^ 0x63; |
FSb[i] = (unsigned char) x; |
RSb[x] = (unsigned char) i; |
} |
/* |
* generate the forward and reverse tables |
*/ |
for( i = 0; i < 256; i++ ) |
{ |
x = FSb[i]; |
y = XTIME( x ) & 0xFF; |
z = ( y ^ x ) & 0xFF; |
FT0[i] = ( (uint32_t) y ) ^ |
( (uint32_t) x << 8 ) ^ |
( (uint32_t) x << 16 ) ^ |
( (uint32_t) z << 24 ); |
#if !defined(MBEDTLS_AES_FEWER_TABLES) |
FT1[i] = ROTL8( FT0[i] ); |
FT2[i] = ROTL8( FT1[i] ); |
FT3[i] = ROTL8( FT2[i] ); |
#endif /* !MBEDTLS_AES_FEWER_TABLES */ |
x = RSb[i]; |
RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ |
( (uint32_t) MUL( 0x09, x ) << 8 ) ^ |
( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ |
( (uint32_t) MUL( 0x0B, x ) << 24 ); |
#if !defined(MBEDTLS_AES_FEWER_TABLES) |
RT1[i] = ROTL8( RT0[i] ); |
RT2[i] = ROTL8( RT1[i] ); |
RT3[i] = ROTL8( RT2[i] ); |
#endif /* !MBEDTLS_AES_FEWER_TABLES */ |
} |
} |
#undef ROTL8 |
#endif /* MBEDTLS_AES_ROM_TABLES */ |
#if defined(MBEDTLS_AES_FEWER_TABLES) |
#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) |
#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) |
#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) |
#define AES_RT0(idx) RT0[idx] |
#define AES_RT1(idx) ROTL8( RT0[idx] ) |
#define AES_RT2(idx) ROTL16( RT0[idx] ) |
#define AES_RT3(idx) ROTL24( RT0[idx] ) |
#define AES_FT0(idx) FT0[idx] |
#define AES_FT1(idx) ROTL8( FT0[idx] ) |
#define AES_FT2(idx) ROTL16( FT0[idx] ) |
#define AES_FT3(idx) ROTL24( FT0[idx] ) |
#else /* MBEDTLS_AES_FEWER_TABLES */ |
#define AES_RT0(idx) RT0[idx] |
#define AES_RT1(idx) RT1[idx] |
#define AES_RT2(idx) RT2[idx] |
#define AES_RT3(idx) RT3[idx] |
#define AES_FT0(idx) FT0[idx] |
#define AES_FT1(idx) FT1[idx] |
#define AES_FT2(idx) FT2[idx] |
#define AES_FT3(idx) FT3[idx] |
#endif /* MBEDTLS_AES_FEWER_TABLES */ |
void mbedtls_aes_init( mbedtls_aes_context *ctx ) |
{ |
AES_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_aes_context ) ); |
} |
void mbedtls_aes_free( mbedtls_aes_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) |
{ |
AES_VALIDATE( ctx != NULL ); |
mbedtls_aes_init( &ctx->crypt ); |
mbedtls_aes_init( &ctx->tweak ); |
} |
void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_aes_free( &ctx->crypt ); |
mbedtls_aes_free( &ctx->tweak ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
/* |
* AES key schedule (encryption) |
*/ |
#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) |
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, |
unsigned int keybits ) |
{ |
unsigned int i; |
uint32_t *RK; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( key != NULL ); |
switch( keybits ) |
{ |
case 128: ctx->nr = 10; break; |
case 192: ctx->nr = 12; break; |
case 256: ctx->nr = 14; break; |
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); |
} |
#if !defined(MBEDTLS_AES_ROM_TABLES) |
if( aes_init_done == 0 ) |
{ |
aes_gen_tables(); |
aes_init_done = 1; |
} |
#endif |
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) |
if( aes_padlock_ace == -1 ) |
aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); |
if( aes_padlock_ace ) |
ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); |
else |
#endif |
ctx->rk = RK = ctx->buf; |
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) |
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) |
return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); |
#endif |
for( i = 0; i < ( keybits >> 5 ); i++ ) |
{ |
GET_UINT32_LE( RK[i], key, i << 2 ); |
} |
switch( ctx->nr ) |
{ |
case 10: |
for( i = 0; i < 10; i++, RK += 4 ) |
{ |
RK[4] = RK[0] ^ RCON[i] ^ |
( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); |
RK[5] = RK[1] ^ RK[4]; |
RK[6] = RK[2] ^ RK[5]; |
RK[7] = RK[3] ^ RK[6]; |
} |
break; |
case 12: |
for( i = 0; i < 8; i++, RK += 6 ) |
{ |
RK[6] = RK[0] ^ RCON[i] ^ |
( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); |
RK[7] = RK[1] ^ RK[6]; |
RK[8] = RK[2] ^ RK[7]; |
RK[9] = RK[3] ^ RK[8]; |
RK[10] = RK[4] ^ RK[9]; |
RK[11] = RK[5] ^ RK[10]; |
} |
break; |
case 14: |
for( i = 0; i < 7; i++, RK += 8 ) |
{ |
RK[8] = RK[0] ^ RCON[i] ^ |
( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); |
RK[9] = RK[1] ^ RK[8]; |
RK[10] = RK[2] ^ RK[9]; |
RK[11] = RK[3] ^ RK[10]; |
RK[12] = RK[4] ^ |
( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); |
RK[13] = RK[5] ^ RK[12]; |
RK[14] = RK[6] ^ RK[13]; |
RK[15] = RK[7] ^ RK[14]; |
} |
break; |
} |
return( 0 ); |
} |
#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ |
/* |
* AES key schedule (decryption) |
*/ |
#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) |
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, |
unsigned int keybits ) |
{ |
int i, j, ret; |
mbedtls_aes_context cty; |
uint32_t *RK; |
uint32_t *SK; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( key != NULL ); |
mbedtls_aes_init( &cty ); |
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) |
if( aes_padlock_ace == -1 ) |
aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); |
if( aes_padlock_ace ) |
ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); |
else |
#endif |
ctx->rk = RK = ctx->buf; |
/* Also checks keybits */ |
if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) |
goto exit; |
ctx->nr = cty.nr; |
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) |
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) |
{ |
mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, |
(const unsigned char *) cty.rk, ctx->nr ); |
goto exit; |
} |
#endif |
SK = cty.rk + cty.nr * 4; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) |
{ |
for( j = 0; j < 4; j++, SK++ ) |
{ |
*RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^ |
AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^ |
AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^ |
AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] ); |
} |
} |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
exit: |
mbedtls_aes_free( &cty ); |
return( ret ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
static int mbedtls_aes_xts_decode_keys( const unsigned char *key, |
unsigned int keybits, |
const unsigned char **key1, |
unsigned int *key1bits, |
const unsigned char **key2, |
unsigned int *key2bits ) |
{ |
const unsigned int half_keybits = keybits / 2; |
const unsigned int half_keybytes = half_keybits / 8; |
switch( keybits ) |
{ |
case 256: break; |
case 512: break; |
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); |
} |
*key1bits = half_keybits; |
*key2bits = half_keybits; |
*key1 = &key[0]; |
*key2 = &key[half_keybytes]; |
return 0; |
} |
int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, |
const unsigned char *key, |
unsigned int keybits) |
{ |
int ret; |
const unsigned char *key1, *key2; |
unsigned int key1bits, key2bits; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( key != NULL ); |
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, |
&key2, &key2bits ); |
if( ret != 0 ) |
return( ret ); |
/* Set the tweak key. Always set tweak key for the encryption mode. */ |
ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); |
if( ret != 0 ) |
return( ret ); |
/* Set crypt key for encryption. */ |
return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); |
} |
int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, |
const unsigned char *key, |
unsigned int keybits) |
{ |
int ret; |
const unsigned char *key1, *key2; |
unsigned int key1bits, key2bits; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( key != NULL ); |
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, |
&key2, &key2bits ); |
if( ret != 0 ) |
return( ret ); |
/* Set the tweak key. Always set tweak key for encryption. */ |
ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); |
if( ret != 0 ) |
return( ret ); |
/* Set crypt key for decryption. */ |
return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ |
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
do \ |
{ \ |
(X0) = *RK++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ |
AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ |
AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ |
AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ |
\ |
(X1) = *RK++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ |
AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ |
AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ |
AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ |
\ |
(X2) = *RK++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ |
AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ |
AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ |
AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ |
\ |
(X3) = *RK++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ |
AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ |
AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ |
AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ |
} while( 0 ) |
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
do \ |
{ \ |
(X0) = *RK++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ |
AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ |
AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ |
AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ |
\ |
(X1) = *RK++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ |
AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ |
AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ |
AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ |
\ |
(X2) = *RK++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ |
AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ |
AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ |
AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ |
\ |
(X3) = *RK++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ |
AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ |
AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ |
AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ |
} while( 0 ) |
/* |
* AES-ECB block encryption |
*/ |
#if !defined(MBEDTLS_AES_ENCRYPT_ALT) |
int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
int i; |
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; |
RK = ctx->rk; |
GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; |
GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; |
GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; |
GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; |
for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) |
{ |
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); |
} |
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
X0 = *RK++ ^ \ |
( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); |
X1 = *RK++ ^ \ |
( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); |
X2 = *RK++ ^ \ |
( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); |
X3 = *RK++ ^ \ |
( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ |
( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); |
PUT_UINT32_LE( X0, output, 0 ); |
PUT_UINT32_LE( X1, output, 4 ); |
PUT_UINT32_LE( X2, output, 8 ); |
PUT_UINT32_LE( X3, output, 12 ); |
mbedtls_platform_zeroize( &X0, sizeof( X0 ) ); |
mbedtls_platform_zeroize( &X1, sizeof( X1 ) ); |
mbedtls_platform_zeroize( &X2, sizeof( X2 ) ); |
mbedtls_platform_zeroize( &X3, sizeof( X3 ) ); |
mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) ); |
mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) ); |
mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) ); |
mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) ); |
mbedtls_platform_zeroize( &RK, sizeof( RK ) ); |
return( 0 ); |
} |
#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
mbedtls_internal_aes_encrypt( ctx, input, output ); |
} |
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ |
/* |
* AES-ECB block decryption |
*/ |
#if !defined(MBEDTLS_AES_DECRYPT_ALT) |
int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
int i; |
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; |
RK = ctx->rk; |
GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; |
GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; |
GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; |
GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; |
for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) |
{ |
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); |
} |
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
X0 = *RK++ ^ \ |
( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ |
( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); |
X1 = *RK++ ^ \ |
( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ |
( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); |
X2 = *RK++ ^ \ |
( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ |
( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); |
X3 = *RK++ ^ \ |
( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ |
( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ |
( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ |
( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); |
PUT_UINT32_LE( X0, output, 0 ); |
PUT_UINT32_LE( X1, output, 4 ); |
PUT_UINT32_LE( X2, output, 8 ); |
PUT_UINT32_LE( X3, output, 12 ); |
mbedtls_platform_zeroize( &X0, sizeof( X0 ) ); |
mbedtls_platform_zeroize( &X1, sizeof( X1 ) ); |
mbedtls_platform_zeroize( &X2, sizeof( X2 ) ); |
mbedtls_platform_zeroize( &X3, sizeof( X3 ) ); |
mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) ); |
mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) ); |
mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) ); |
mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) ); |
mbedtls_platform_zeroize( &RK, sizeof( RK ) ); |
return( 0 ); |
} |
#endif /* !MBEDTLS_AES_DECRYPT_ALT */ |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
mbedtls_internal_aes_decrypt( ctx, input, output ); |
} |
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ |
/* |
* AES-ECB block encryption/decryption |
*/ |
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, |
int mode, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( input != NULL ); |
AES_VALIDATE_RET( output != NULL ); |
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || |
mode == MBEDTLS_AES_DECRYPT ); |
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) |
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) |
return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); |
#endif |
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) |
if( aes_padlock_ace ) |
{ |
if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) |
return( 0 ); |
// If padlock data misaligned, we just fall back to |
// unaccelerated mode |
// |
} |
#endif |
if( mode == MBEDTLS_AES_ENCRYPT ) |
return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); |
else |
return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* AES-CBC buffer encryption/decryption |
*/ |
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int i; |
unsigned char temp[16]; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || |
mode == MBEDTLS_AES_DECRYPT ); |
AES_VALIDATE_RET( iv != NULL ); |
AES_VALIDATE_RET( input != NULL ); |
AES_VALIDATE_RET( output != NULL ); |
if( length % 16 ) |
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); |
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) |
if( aes_padlock_ace ) |
{ |
if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) |
return( 0 ); |
// If padlock data misaligned, we just fall back to |
// unaccelerated mode |
// |
} |
#endif |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, 16 ); |
mbedtls_aes_crypt_ecb( ctx, mode, input, output ); |
for( i = 0; i < 16; i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, 16 ); |
input += 16; |
output += 16; |
length -= 16; |
} |
} |
else |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < 16; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
mbedtls_aes_crypt_ecb( ctx, mode, output, output ); |
memcpy( iv, output, 16 ); |
input += 16; |
output += 16; |
length -= 16; |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
/* Endianess with 64 bits values */ |
#ifndef GET_UINT64_LE |
#define GET_UINT64_LE(n,b,i) \ |
{ \ |
(n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ |
| ( (uint64_t) (b)[(i) + 6] << 48 ) \ |
| ( (uint64_t) (b)[(i) + 5] << 40 ) \ |
| ( (uint64_t) (b)[(i) + 4] << 32 ) \ |
| ( (uint64_t) (b)[(i) + 3] << 24 ) \ |
| ( (uint64_t) (b)[(i) + 2] << 16 ) \ |
| ( (uint64_t) (b)[(i) + 1] << 8 ) \ |
| ( (uint64_t) (b)[(i) ] ); \ |
} |
#endif |
#ifndef PUT_UINT64_LE |
#define PUT_UINT64_LE(n,b,i) \ |
{ \ |
(b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ |
(b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ |
(b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ |
(b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) ] = (unsigned char) ( (n) ); \ |
} |
#endif |
typedef unsigned char mbedtls_be128[16]; |
/* |
* GF(2^128) multiplication function |
* |
* This function multiplies a field element by x in the polynomial field |
* representation. It uses 64-bit word operations to gain speed but compensates |
* for machine endianess and hence works correctly on both big and little |
* endian machines. |
*/ |
static void mbedtls_gf128mul_x_ble( unsigned char r[16], |
const unsigned char x[16] ) |
{ |
uint64_t a, b, ra, rb; |
GET_UINT64_LE( a, x, 0 ); |
GET_UINT64_LE( b, x, 8 ); |
ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); |
rb = ( a >> 63 ) | ( b << 1 ); |
PUT_UINT64_LE( ra, r, 0 ); |
PUT_UINT64_LE( rb, r, 8 ); |
} |
/* |
* AES-XTS buffer encryption/decryption |
*/ |
int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, |
int mode, |
size_t length, |
const unsigned char data_unit[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
size_t blocks = length / 16; |
size_t leftover = length % 16; |
unsigned char tweak[16]; |
unsigned char prev_tweak[16]; |
unsigned char tmp[16]; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || |
mode == MBEDTLS_AES_DECRYPT ); |
AES_VALIDATE_RET( data_unit != NULL ); |
AES_VALIDATE_RET( input != NULL ); |
AES_VALIDATE_RET( output != NULL ); |
/* Data units must be at least 16 bytes long. */ |
if( length < 16 ) |
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; |
/* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ |
if( length > ( 1 << 20 ) * 16 ) |
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; |
/* Compute the tweak. */ |
ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, |
data_unit, tweak ); |
if( ret != 0 ) |
return( ret ); |
while( blocks-- ) |
{ |
size_t i; |
if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) |
{ |
/* We are on the last block in a decrypt operation that has |
* leftover bytes, so we need to use the next tweak for this block, |
* and this tweak for the lefover bytes. Save the current tweak for |
* the leftovers and then update the current tweak for use on this, |
* the last full block. */ |
memcpy( prev_tweak, tweak, sizeof( tweak ) ); |
mbedtls_gf128mul_x_ble( tweak, tweak ); |
} |
for( i = 0; i < 16; i++ ) |
tmp[i] = input[i] ^ tweak[i]; |
ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); |
if( ret != 0 ) |
return( ret ); |
for( i = 0; i < 16; i++ ) |
output[i] = tmp[i] ^ tweak[i]; |
/* Update the tweak for the next block. */ |
mbedtls_gf128mul_x_ble( tweak, tweak ); |
output += 16; |
input += 16; |
} |
if( leftover ) |
{ |
/* If we are on the leftover bytes in a decrypt operation, we need to |
* use the previous tweak for these bytes (as saved in prev_tweak). */ |
unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; |
/* We are now on the final part of the data unit, which doesn't divide |
* evenly by 16. It's time for ciphertext stealing. */ |
size_t i; |
unsigned char *prev_output = output - 16; |
/* Copy ciphertext bytes from the previous block to our output for each |
* byte of cyphertext we won't steal. At the same time, copy the |
* remainder of the input for this final round (since the loop bounds |
* are the same). */ |
for( i = 0; i < leftover; i++ ) |
{ |
output[i] = prev_output[i]; |
tmp[i] = input[i] ^ t[i]; |
} |
/* Copy ciphertext bytes from the previous block for input in this |
* round. */ |
for( ; i < 16; i++ ) |
tmp[i] = prev_output[i] ^ t[i]; |
ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); |
if( ret != 0 ) |
return ret; |
/* Write the result back to the previous block, overriding the previous |
* output we copied. */ |
for( i = 0; i < 16; i++ ) |
prev_output[i] = tmp[i] ^ t[i]; |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
/* |
* AES-CFB128 buffer encryption/decryption |
*/ |
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, |
int mode, |
size_t length, |
size_t *iv_off, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c; |
size_t n; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || |
mode == MBEDTLS_AES_DECRYPT ); |
AES_VALIDATE_RET( iv_off != NULL ); |
AES_VALIDATE_RET( iv != NULL ); |
AES_VALIDATE_RET( input != NULL ); |
AES_VALIDATE_RET( output != NULL ); |
n = *iv_off; |
if( n > 15 ) |
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); |
c = *input++; |
*output++ = (unsigned char)( c ^ iv[n] ); |
iv[n] = (unsigned char) c; |
n = ( n + 1 ) & 0x0F; |
} |
} |
else |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); |
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); |
n = ( n + 1 ) & 0x0F; |
} |
} |
*iv_off = n; |
return( 0 ); |
} |
/* |
* AES-CFB8 buffer encryption/decryption |
*/ |
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
unsigned char c; |
unsigned char ov[17]; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || |
mode == MBEDTLS_AES_DECRYPT ); |
AES_VALIDATE_RET( iv != NULL ); |
AES_VALIDATE_RET( input != NULL ); |
AES_VALIDATE_RET( output != NULL ); |
while( length-- ) |
{ |
memcpy( ov, iv, 16 ); |
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); |
if( mode == MBEDTLS_AES_DECRYPT ) |
ov[16] = *input; |
c = *output++ = (unsigned char)( iv[0] ^ *input++ ); |
if( mode == MBEDTLS_AES_ENCRYPT ) |
ov[16] = c; |
memcpy( iv, ov + 1, 16 ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
/* |
* AES-OFB (Output Feedback Mode) buffer encryption/decryption |
*/ |
int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, |
size_t length, |
size_t *iv_off, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret = 0; |
size_t n; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( iv_off != NULL ); |
AES_VALIDATE_RET( iv != NULL ); |
AES_VALIDATE_RET( input != NULL ); |
AES_VALIDATE_RET( output != NULL ); |
n = *iv_off; |
if( n > 15 ) |
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); |
while( length-- ) |
{ |
if( n == 0 ) |
{ |
ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); |
if( ret != 0 ) |
goto exit; |
} |
*output++ = *input++ ^ iv[n]; |
n = ( n + 1 ) & 0x0F; |
} |
*iv_off = n; |
exit: |
return( ret ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_OFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* AES-CTR buffer encryption/decryption |
*/ |
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, |
size_t length, |
size_t *nc_off, |
unsigned char nonce_counter[16], |
unsigned char stream_block[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c, i; |
size_t n; |
AES_VALIDATE_RET( ctx != NULL ); |
AES_VALIDATE_RET( nc_off != NULL ); |
AES_VALIDATE_RET( nonce_counter != NULL ); |
AES_VALIDATE_RET( stream_block != NULL ); |
AES_VALIDATE_RET( input != NULL ); |
AES_VALIDATE_RET( output != NULL ); |
n = *nc_off; |
if ( n > 0x0F ) |
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); |
while( length-- ) |
{ |
if( n == 0 ) { |
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); |
for( i = 16; i > 0; i-- ) |
if( ++nonce_counter[i - 1] != 0 ) |
break; |
} |
c = *input++; |
*output++ = (unsigned char)( c ^ stream_block[n] ); |
n = ( n + 1 ) & 0x0F; |
} |
*nc_off = n; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#endif /* !MBEDTLS_AES_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* AES test vectors from: |
* |
* http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip |
*/ |
static const unsigned char aes_test_ecb_dec[3][16] = |
{ |
{ 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, |
0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, |
{ 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, |
0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, |
{ 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, |
0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } |
}; |
static const unsigned char aes_test_ecb_enc[3][16] = |
{ |
{ 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, |
0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, |
{ 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, |
0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, |
{ 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, |
0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const unsigned char aes_test_cbc_dec[3][16] = |
{ |
{ 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, |
0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, |
{ 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, |
0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, |
{ 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, |
0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } |
}; |
static const unsigned char aes_test_cbc_enc[3][16] = |
{ |
{ 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, |
0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, |
{ 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, |
0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, |
{ 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, |
0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
/* |
* AES-CFB128 test vectors from: |
* |
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf |
*/ |
static const unsigned char aes_test_cfb128_key[3][32] = |
{ |
{ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, |
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, |
{ 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, |
0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, |
0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, |
{ 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, |
0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, |
0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, |
0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } |
}; |
static const unsigned char aes_test_cfb128_iv[16] = |
{ |
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F |
}; |
static const unsigned char aes_test_cfb128_pt[64] = |
{ |
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, |
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, |
0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, |
0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, |
0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, |
0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, |
0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, |
0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 |
}; |
static const unsigned char aes_test_cfb128_ct[3][64] = |
{ |
{ 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, |
0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, |
0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, |
0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, |
0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, |
0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, |
0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, |
0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, |
{ 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, |
0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, |
0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, |
0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, |
0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, |
0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, |
0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, |
0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, |
{ 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, |
0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, |
0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, |
0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, |
0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, |
0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, |
0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, |
0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
/* |
* AES-OFB test vectors from: |
* |
* https://csrc.nist.gov/publications/detail/sp/800-38a/final |
*/ |
static const unsigned char aes_test_ofb_key[3][32] = |
{ |
{ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, |
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, |
{ 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, |
0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, |
0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, |
{ 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, |
0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, |
0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, |
0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } |
}; |
static const unsigned char aes_test_ofb_iv[16] = |
{ |
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F |
}; |
static const unsigned char aes_test_ofb_pt[64] = |
{ |
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, |
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, |
0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, |
0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, |
0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, |
0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, |
0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, |
0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 |
}; |
static const unsigned char aes_test_ofb_ct[3][64] = |
{ |
{ 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, |
0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, |
0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, |
0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, |
0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, |
0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, |
0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, |
0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, |
{ 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, |
0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, |
0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, |
0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, |
0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, |
0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, |
0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, |
0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, |
{ 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, |
0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, |
0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, |
0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, |
0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, |
0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, |
0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, |
0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } |
}; |
#endif /* MBEDTLS_CIPHER_MODE_OFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* AES-CTR test vectors from: |
* |
* http://www.faqs.org/rfcs/rfc3686.html |
*/ |
static const unsigned char aes_test_ctr_key[3][16] = |
{ |
{ 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, |
0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, |
{ 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, |
0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, |
{ 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, |
0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } |
}; |
static const unsigned char aes_test_ctr_nonce_counter[3][16] = |
{ |
{ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, |
{ 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, |
0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, |
{ 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, |
0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } |
}; |
static const unsigned char aes_test_ctr_pt[3][48] = |
{ |
{ 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, |
0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, |
0x20, 0x21, 0x22, 0x23 } |
}; |
static const unsigned char aes_test_ctr_ct[3][48] = |
{ |
{ 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, |
0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, |
{ 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, |
0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, |
0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, |
0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, |
{ 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, |
0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, |
0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, |
0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, |
0x25, 0xB2, 0x07, 0x2F } |
}; |
static const int aes_test_ctr_len[3] = |
{ 16, 32, 36 }; |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
/* |
* AES-XTS test vectors from: |
* |
* IEEE P1619/D16 Annex B |
* https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf |
* (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) |
*/ |
static const unsigned char aes_test_xts_key[][32] = |
{ |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
{ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, |
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, |
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, |
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, |
{ 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, |
0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, |
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, |
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, |
}; |
static const unsigned char aes_test_xts_pt32[][32] = |
{ |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, |
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, |
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, |
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, |
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, |
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, |
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, |
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, |
}; |
static const unsigned char aes_test_xts_ct32[][32] = |
{ |
{ 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, |
0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, |
0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, |
0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, |
{ 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, |
0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, |
0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, |
0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, |
{ 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, |
0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, |
0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, |
0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, |
}; |
static const unsigned char aes_test_xts_data_unit[][16] = |
{ |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
}; |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
/* |
* Checkup routine |
*/ |
int mbedtls_aes_self_test( int verbose ) |
{ |
int ret = 0, i, j, u, mode; |
unsigned int keybits; |
unsigned char key[32]; |
unsigned char buf[64]; |
const unsigned char *aes_tests; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) |
unsigned char iv[16]; |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
unsigned char prv[16]; |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ |
defined(MBEDTLS_CIPHER_MODE_OFB) |
size_t offset; |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) |
int len; |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
unsigned char nonce_counter[16]; |
unsigned char stream_block[16]; |
#endif |
mbedtls_aes_context ctx; |
memset( key, 0, 32 ); |
mbedtls_aes_init( &ctx ); |
/* |
* ECB mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
keybits = 128 + u * 64; |
mode = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " AES-ECB-%3d (%s): ", keybits, |
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); |
memset( buf, 0, 16 ); |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); |
aes_tests = aes_test_ecb_dec[u]; |
} |
else |
{ |
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); |
aes_tests = aes_test_ecb_enc[u]; |
} |
/* |
* AES-192 is an optional feature that may be unavailable when |
* there is an alternative underlying implementation i.e. when |
* MBEDTLS_AES_ALT is defined. |
*/ |
if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) |
{ |
mbedtls_printf( "skipped\n" ); |
continue; |
} |
else if( ret != 0 ) |
{ |
goto exit; |
} |
for( j = 0; j < 10000; j++ ) |
{ |
ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); |
if( ret != 0 ) |
goto exit; |
} |
if( memcmp( buf, aes_tests, 16 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* CBC mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
keybits = 128 + u * 64; |
mode = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " AES-CBC-%3d (%s): ", keybits, |
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); |
memset( iv , 0, 16 ); |
memset( prv, 0, 16 ); |
memset( buf, 0, 16 ); |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); |
aes_tests = aes_test_cbc_dec[u]; |
} |
else |
{ |
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); |
aes_tests = aes_test_cbc_enc[u]; |
} |
/* |
* AES-192 is an optional feature that may be unavailable when |
* there is an alternative underlying implementation i.e. when |
* MBEDTLS_AES_ALT is defined. |
*/ |
if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) |
{ |
mbedtls_printf( "skipped\n" ); |
continue; |
} |
else if( ret != 0 ) |
{ |
goto exit; |
} |
for( j = 0; j < 10000; j++ ) |
{ |
if( mode == MBEDTLS_AES_ENCRYPT ) |
{ |
unsigned char tmp[16]; |
memcpy( tmp, prv, 16 ); |
memcpy( prv, buf, 16 ); |
memcpy( buf, tmp, 16 ); |
} |
ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); |
if( ret != 0 ) |
goto exit; |
} |
if( memcmp( buf, aes_tests, 16 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
/* |
* CFB128 mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
keybits = 128 + u * 64; |
mode = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits, |
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); |
memcpy( iv, aes_test_cfb128_iv, 16 ); |
memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); |
offset = 0; |
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); |
/* |
* AES-192 is an optional feature that may be unavailable when |
* there is an alternative underlying implementation i.e. when |
* MBEDTLS_AES_ALT is defined. |
*/ |
if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) |
{ |
mbedtls_printf( "skipped\n" ); |
continue; |
} |
else if( ret != 0 ) |
{ |
goto exit; |
} |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
memcpy( buf, aes_test_cfb128_ct[u], 64 ); |
aes_tests = aes_test_cfb128_pt; |
} |
else |
{ |
memcpy( buf, aes_test_cfb128_pt, 64 ); |
aes_tests = aes_test_cfb128_ct[u]; |
} |
ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); |
if( ret != 0 ) |
goto exit; |
if( memcmp( buf, aes_tests, 64 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
/* |
* OFB mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
keybits = 128 + u * 64; |
mode = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " AES-OFB-%3d (%s): ", keybits, |
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); |
memcpy( iv, aes_test_ofb_iv, 16 ); |
memcpy( key, aes_test_ofb_key[u], keybits / 8 ); |
offset = 0; |
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); |
/* |
* AES-192 is an optional feature that may be unavailable when |
* there is an alternative underlying implementation i.e. when |
* MBEDTLS_AES_ALT is defined. |
*/ |
if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) |
{ |
mbedtls_printf( "skipped\n" ); |
continue; |
} |
else if( ret != 0 ) |
{ |
goto exit; |
} |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
memcpy( buf, aes_test_ofb_ct[u], 64 ); |
aes_tests = aes_test_ofb_pt; |
} |
else |
{ |
memcpy( buf, aes_test_ofb_pt, 64 ); |
aes_tests = aes_test_ofb_ct[u]; |
} |
ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); |
if( ret != 0 ) |
goto exit; |
if( memcmp( buf, aes_tests, 64 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_OFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* CTR mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
mode = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " AES-CTR-128 (%s): ", |
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); |
memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); |
memcpy( key, aes_test_ctr_key[u], 16 ); |
offset = 0; |
if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) |
goto exit; |
len = aes_test_ctr_len[u]; |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
memcpy( buf, aes_test_ctr_ct[u], len ); |
aes_tests = aes_test_ctr_pt[u]; |
} |
else |
{ |
memcpy( buf, aes_test_ctr_pt[u], len ); |
aes_tests = aes_test_ctr_ct[u]; |
} |
ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, |
stream_block, buf, buf ); |
if( ret != 0 ) |
goto exit; |
if( memcmp( buf, aes_tests, len ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
{ |
static const int num_tests = |
sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); |
mbedtls_aes_xts_context ctx_xts; |
/* |
* XTS mode |
*/ |
mbedtls_aes_xts_init( &ctx_xts ); |
for( i = 0; i < num_tests << 1; i++ ) |
{ |
const unsigned char *data_unit; |
u = i >> 1; |
mode = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " AES-XTS-128 (%s): ", |
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); |
memset( key, 0, sizeof( key ) ); |
memcpy( key, aes_test_xts_key[u], 32 ); |
data_unit = aes_test_xts_data_unit[u]; |
len = sizeof( *aes_test_xts_ct32 ); |
if( mode == MBEDTLS_AES_DECRYPT ) |
{ |
ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); |
if( ret != 0) |
goto exit; |
memcpy( buf, aes_test_xts_ct32[u], len ); |
aes_tests = aes_test_xts_pt32[u]; |
} |
else |
{ |
ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); |
if( ret != 0) |
goto exit; |
memcpy( buf, aes_test_xts_pt32[u], len ); |
aes_tests = aes_test_xts_ct32[u]; |
} |
ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, |
buf, buf ); |
if( ret != 0 ) |
goto exit; |
if( memcmp( buf, aes_tests, len ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
mbedtls_aes_xts_free( &ctx_xts ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
ret = 0; |
exit: |
if( ret != 0 && verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
mbedtls_aes_free( &ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_AES_C */ |
/programs/develop/libraries/kos_mbedtls/library/aesni.c |
---|
0,0 → 1,472 |
/* |
* AES-NI support functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set |
* [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_AESNI_C) |
#if defined(__has_feature) |
#if __has_feature(memory_sanitizer) |
#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." |
#endif |
#endif |
#include "mbedtls/aesni.h" |
#include <string.h> |
#ifndef asm |
#define asm __asm |
#endif |
#if defined(MBEDTLS_HAVE_X86_64) |
/* |
* AES-NI support detection routine |
*/ |
int mbedtls_aesni_has_support( unsigned int what ) |
{ |
static int done = 0; |
static unsigned int c = 0; |
if( ! done ) |
{ |
asm( "movl $1, %%eax \n\t" |
"cpuid \n\t" |
: "=c" (c) |
: |
: "eax", "ebx", "edx" ); |
done = 1; |
} |
return( ( c & what ) != 0 ); |
} |
/* |
* Binutils needs to be at least 2.19 to support AES-NI instructions. |
* Unfortunately, a lot of users have a lower version now (2014-04). |
* Emit bytecode directly in order to support "old" version of gas. |
* |
* Opcodes from the Intel architecture reference manual, vol. 3. |
* We always use registers, so we don't need prefixes for memory operands. |
* Operand macros are in gas order (src, dst) as opposed to Intel order |
* (dst, src) in order to blend better into the surrounding assembly code. |
*/ |
#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," |
#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," |
#define AESENC ".byte 0x66,0x0F,0x38,0xDC," |
#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," |
#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," |
#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," |
#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," |
#define xmm0_xmm0 "0xC0" |
#define xmm0_xmm1 "0xC8" |
#define xmm0_xmm2 "0xD0" |
#define xmm0_xmm3 "0xD8" |
#define xmm0_xmm4 "0xE0" |
#define xmm1_xmm0 "0xC1" |
#define xmm1_xmm2 "0xD1" |
/* |
* AES-NI AES-ECB block en(de)cryption |
*/ |
int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, |
int mode, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
asm( "movdqu (%3), %%xmm0 \n\t" // load input |
"movdqu (%1), %%xmm1 \n\t" // load round key 0 |
"pxor %%xmm1, %%xmm0 \n\t" // round 0 |
"add $16, %1 \n\t" // point to next round key |
"subl $1, %0 \n\t" // normal rounds = nr - 1 |
"test %2, %2 \n\t" // mode? |
"jz 2f \n\t" // 0 = decrypt |
"1: \n\t" // encryption loop |
"movdqu (%1), %%xmm1 \n\t" // load round key |
AESENC xmm1_xmm0 "\n\t" // do round |
"add $16, %1 \n\t" // point to next round key |
"subl $1, %0 \n\t" // loop |
"jnz 1b \n\t" |
"movdqu (%1), %%xmm1 \n\t" // load round key |
AESENCLAST xmm1_xmm0 "\n\t" // last round |
"jmp 3f \n\t" |
"2: \n\t" // decryption loop |
"movdqu (%1), %%xmm1 \n\t" |
AESDEC xmm1_xmm0 "\n\t" // do round |
"add $16, %1 \n\t" |
"subl $1, %0 \n\t" |
"jnz 2b \n\t" |
"movdqu (%1), %%xmm1 \n\t" // load round key |
AESDECLAST xmm1_xmm0 "\n\t" // last round |
"3: \n\t" |
"movdqu %%xmm0, (%4) \n\t" // export output |
: |
: "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) |
: "memory", "cc", "xmm0", "xmm1" ); |
return( 0 ); |
} |
/* |
* GCM multiplication: c = a times b in GF(2^128) |
* Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. |
*/ |
void mbedtls_aesni_gcm_mult( unsigned char c[16], |
const unsigned char a[16], |
const unsigned char b[16] ) |
{ |
unsigned char aa[16], bb[16], cc[16]; |
size_t i; |
/* The inputs are in big-endian order, so byte-reverse them */ |
for( i = 0; i < 16; i++ ) |
{ |
aa[i] = a[15 - i]; |
bb[i] = b[15 - i]; |
} |
asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 |
"movdqu (%1), %%xmm1 \n\t" // b1:b0 |
/* |
* Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 |
* using [CLMUL-WP] algorithm 1 (p. 13). |
*/ |
"movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 |
"movdqa %%xmm1, %%xmm3 \n\t" // same |
"movdqa %%xmm1, %%xmm4 \n\t" // same |
PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 |
PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 |
PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 |
PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 |
"pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 |
"movdqa %%xmm4, %%xmm3 \n\t" // same |
"psrldq $8, %%xmm4 \n\t" // 0:e1+f1 |
"pslldq $8, %%xmm3 \n\t" // e0+f0:0 |
"pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 |
"pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 |
/* |
* Now shift the result one bit to the left, |
* taking advantage of [CLMUL-WP] eq 27 (p. 20) |
*/ |
"movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 |
"movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 |
"psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 |
"psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 |
"psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 |
"psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 |
"movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 |
"pslldq $8, %%xmm3 \n\t" // r0>>63:0 |
"pslldq $8, %%xmm4 \n\t" // r2>>63:0 |
"psrldq $8, %%xmm5 \n\t" // 0:r1>>63 |
"por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 |
"por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 |
"por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 |
/* |
* Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 |
* using [CLMUL-WP] algorithm 5 (p. 20). |
* Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). |
*/ |
/* Step 2 (1) */ |
"movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 |
"movdqa %%xmm1, %%xmm4 \n\t" // same |
"movdqa %%xmm1, %%xmm5 \n\t" // same |
"psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a |
"psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b |
"psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c |
/* Step 2 (2) */ |
"pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b |
"pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c |
"pslldq $8, %%xmm3 \n\t" // a+b+c:0 |
"pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 |
/* Steps 3 and 4 */ |
"movdqa %%xmm1,%%xmm0 \n\t" // d:x0 |
"movdqa %%xmm1,%%xmm4 \n\t" // same |
"movdqa %%xmm1,%%xmm5 \n\t" // same |
"psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' |
"psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' |
"psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' |
"pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' |
"pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' |
// e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing |
// bits carried from d. Now get those\t bits back in. |
"movdqa %%xmm1,%%xmm3 \n\t" // d:x0 |
"movdqa %%xmm1,%%xmm4 \n\t" // same |
"movdqa %%xmm1,%%xmm5 \n\t" // same |
"psllq $63, %%xmm3 \n\t" // d<<63:stuff |
"psllq $62, %%xmm4 \n\t" // d<<62:stuff |
"psllq $57, %%xmm5 \n\t" // d<<57:stuff |
"pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff |
"pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff |
"psrldq $8, %%xmm3 \n\t" // 0:missing bits of d |
"pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 |
"pxor %%xmm1, %%xmm0 \n\t" // h1:h0 |
"pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 |
"movdqu %%xmm0, (%2) \n\t" // done |
: |
: "r" (aa), "r" (bb), "r" (cc) |
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); |
/* Now byte-reverse the outputs */ |
for( i = 0; i < 16; i++ ) |
c[i] = cc[15 - i]; |
return; |
} |
/* |
* Compute decryption round keys from encryption round keys |
*/ |
void mbedtls_aesni_inverse_key( unsigned char *invkey, |
const unsigned char *fwdkey, int nr ) |
{ |
unsigned char *ik = invkey; |
const unsigned char *fk = fwdkey + 16 * nr; |
memcpy( ik, fk, 16 ); |
for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) |
asm( "movdqu (%0), %%xmm0 \n\t" |
AESIMC xmm0_xmm0 "\n\t" |
"movdqu %%xmm0, (%1) \n\t" |
: |
: "r" (fk), "r" (ik) |
: "memory", "xmm0" ); |
memcpy( ik, fk, 16 ); |
} |
/* |
* Key expansion, 128-bit case |
*/ |
static void aesni_setkey_enc_128( unsigned char *rk, |
const unsigned char *key ) |
{ |
asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key |
"movdqu %%xmm0, (%0) \n\t" // as round key 0 |
"jmp 2f \n\t" // skip auxiliary routine |
/* |
* Finish generating the next round key. |
* |
* On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff |
* with X = rot( sub( r3 ) ) ^ RCON. |
* |
* On exit, xmm0 is r7:r6:r5:r4 |
* with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 |
* and those are written to the round key buffer. |
*/ |
"1: \n\t" |
"pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X |
"pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 |
"pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 |
"pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 |
"pslldq $4, %%xmm0 \n\t" // etc |
"pxor %%xmm0, %%xmm1 \n\t" |
"pslldq $4, %%xmm0 \n\t" |
"pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! |
"add $16, %0 \n\t" // point to next round key |
"movdqu %%xmm0, (%0) \n\t" // write it |
"ret \n\t" |
/* Main "loop" */ |
"2: \n\t" |
AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" |
AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" |
: |
: "r" (rk), "r" (key) |
: "memory", "cc", "0" ); |
} |
/* |
* Key expansion, 192-bit case |
*/ |
static void aesni_setkey_enc_192( unsigned char *rk, |
const unsigned char *key ) |
{ |
asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key |
"movdqu %%xmm0, (%0) \n\t" |
"add $16, %0 \n\t" |
"movq 16(%1), %%xmm1 \n\t" |
"movq %%xmm1, (%0) \n\t" |
"add $8, %0 \n\t" |
"jmp 2f \n\t" // skip auxiliary routine |
/* |
* Finish generating the next 6 quarter-keys. |
* |
* On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 |
* and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. |
* |
* On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 |
* and those are written to the round key buffer. |
*/ |
"1: \n\t" |
"pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X |
"pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 |
"pslldq $4, %%xmm0 \n\t" // etc |
"pxor %%xmm0, %%xmm2 \n\t" |
"pslldq $4, %%xmm0 \n\t" |
"pxor %%xmm0, %%xmm2 \n\t" |
"pslldq $4, %%xmm0 \n\t" |
"pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 |
"movdqu %%xmm0, (%0) \n\t" |
"add $16, %0 \n\t" |
"pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 |
"pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 |
"pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 |
"pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 |
"movq %%xmm1, (%0) \n\t" |
"add $8, %0 \n\t" |
"ret \n\t" |
"2: \n\t" |
AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" |
: |
: "r" (rk), "r" (key) |
: "memory", "cc", "0" ); |
} |
/* |
* Key expansion, 256-bit case |
*/ |
static void aesni_setkey_enc_256( unsigned char *rk, |
const unsigned char *key ) |
{ |
asm( "movdqu (%1), %%xmm0 \n\t" |
"movdqu %%xmm0, (%0) \n\t" |
"add $16, %0 \n\t" |
"movdqu 16(%1), %%xmm1 \n\t" |
"movdqu %%xmm1, (%0) \n\t" |
"jmp 2f \n\t" // skip auxiliary routine |
/* |
* Finish generating the next two round keys. |
* |
* On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and |
* xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON |
* |
* On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 |
* and those have been written to the output buffer. |
*/ |
"1: \n\t" |
"pshufd $0xff, %%xmm2, %%xmm2 \n\t" |
"pxor %%xmm0, %%xmm2 \n\t" |
"pslldq $4, %%xmm0 \n\t" |
"pxor %%xmm0, %%xmm2 \n\t" |
"pslldq $4, %%xmm0 \n\t" |
"pxor %%xmm0, %%xmm2 \n\t" |
"pslldq $4, %%xmm0 \n\t" |
"pxor %%xmm2, %%xmm0 \n\t" |
"add $16, %0 \n\t" |
"movdqu %%xmm0, (%0) \n\t" |
/* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) |
* and proceed to generate next round key from there */ |
AESKEYGENA xmm0_xmm2 ",0x00 \n\t" |
"pshufd $0xaa, %%xmm2, %%xmm2 \n\t" |
"pxor %%xmm1, %%xmm2 \n\t" |
"pslldq $4, %%xmm1 \n\t" |
"pxor %%xmm1, %%xmm2 \n\t" |
"pslldq $4, %%xmm1 \n\t" |
"pxor %%xmm1, %%xmm2 \n\t" |
"pslldq $4, %%xmm1 \n\t" |
"pxor %%xmm2, %%xmm1 \n\t" |
"add $16, %0 \n\t" |
"movdqu %%xmm1, (%0) \n\t" |
"ret \n\t" |
/* |
* Main "loop" - Generating one more key than necessary, |
* see definition of mbedtls_aes_context.buf |
*/ |
"2: \n\t" |
AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" |
AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" |
: |
: "r" (rk), "r" (key) |
: "memory", "cc", "0" ); |
} |
/* |
* Key expansion, wrapper |
*/ |
int mbedtls_aesni_setkey_enc( unsigned char *rk, |
const unsigned char *key, |
size_t bits ) |
{ |
switch( bits ) |
{ |
case 128: aesni_setkey_enc_128( rk, key ); break; |
case 192: aesni_setkey_enc_192( rk, key ); break; |
case 256: aesni_setkey_enc_256( rk, key ); break; |
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_HAVE_X86_64 */ |
#endif /* MBEDTLS_AESNI_C */ |
/programs/develop/libraries/kos_mbedtls/library/arc4.c |
---|
0,0 → 1,203 |
/* |
* An implementation of the ARCFOUR algorithm |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The ARCFOUR algorithm was publicly disclosed on 94/09. |
* |
* http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ARC4_C) |
#include "mbedtls/arc4.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_ARC4_ALT) |
void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); |
} |
void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); |
} |
/* |
* ARC4 key schedule |
*/ |
void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, |
unsigned int keylen ) |
{ |
int i, j, a; |
unsigned int k; |
unsigned char *m; |
ctx->x = 0; |
ctx->y = 0; |
m = ctx->m; |
for( i = 0; i < 256; i++ ) |
m[i] = (unsigned char) i; |
j = k = 0; |
for( i = 0; i < 256; i++, k++ ) |
{ |
if( k >= keylen ) k = 0; |
a = m[i]; |
j = ( j + a + key[k] ) & 0xFF; |
m[i] = m[j]; |
m[j] = (unsigned char) a; |
} |
} |
/* |
* ARC4 cipher function |
*/ |
int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, |
unsigned char *output ) |
{ |
int x, y, a, b; |
size_t i; |
unsigned char *m; |
x = ctx->x; |
y = ctx->y; |
m = ctx->m; |
for( i = 0; i < length; i++ ) |
{ |
x = ( x + 1 ) & 0xFF; a = m[x]; |
y = ( y + a ) & 0xFF; b = m[y]; |
m[x] = (unsigned char) b; |
m[y] = (unsigned char) a; |
output[i] = (unsigned char) |
( input[i] ^ m[(unsigned char)( a + b )] ); |
} |
ctx->x = x; |
ctx->y = y; |
return( 0 ); |
} |
#endif /* !MBEDTLS_ARC4_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: |
* |
* http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 |
*/ |
static const unsigned char arc4_test_key[3][8] = |
{ |
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, |
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } |
}; |
static const unsigned char arc4_test_pt[3][8] = |
{ |
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } |
}; |
static const unsigned char arc4_test_ct[3][8] = |
{ |
{ 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, |
{ 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, |
{ 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_arc4_self_test( int verbose ) |
{ |
int i, ret = 0; |
unsigned char ibuf[8]; |
unsigned char obuf[8]; |
mbedtls_arc4_context ctx; |
mbedtls_arc4_init( &ctx ); |
for( i = 0; i < 3; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " ARC4 test #%d: ", i + 1 ); |
memcpy( ibuf, arc4_test_pt[i], 8 ); |
mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); |
mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); |
if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
exit: |
mbedtls_arc4_free( &ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_ARC4_C */ |
/programs/develop/libraries/kos_mbedtls/library/aria.c |
---|
0,0 → 1,1081 |
/* |
* ARIA implementation |
* |
* Copyright (C) 2006-2017, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* This implementation is based on the following standards: |
* [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf |
* [2] https://tools.ietf.org/html/rfc5794 |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ARIA_C) |
#include "mbedtls/aria.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_ARIA_ALT) |
#include "mbedtls/platform_util.h" |
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ |
!defined(inline) && !defined(__cplusplus) |
#define inline __inline |
#endif |
/* Parameter validation macros */ |
#define ARIA_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) |
#define ARIA_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* 32-bit integer manipulation macros (little endian) |
*/ |
#ifndef GET_UINT32_LE |
#define GET_UINT32_LE( n, b, i ) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] ) \ |
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 3] << 24 ); \ |
} |
#endif |
#ifndef PUT_UINT32_LE |
#define PUT_UINT32_LE( n, b, i ) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ |
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ |
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ |
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ |
} |
#endif |
/* |
* modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes |
* |
* This is submatrix P1 in [1] Appendix B.1 |
* |
* Common compilers fail to translate this to minimal number of instructions, |
* so let's provide asm versions for common platforms with C fallback. |
*/ |
#if defined(MBEDTLS_HAVE_ASM) |
#if defined(__arm__) /* rev16 available from v6 up */ |
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ |
#if defined(__GNUC__) && \ |
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ |
__ARM_ARCH >= 6 |
static inline uint32_t aria_p1( uint32_t x ) |
{ |
uint32_t r; |
__asm( "rev16 %0, %1" : "=l" (r) : "l" (x) ); |
return( r ); |
} |
#define ARIA_P1 aria_p1 |
#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ |
( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) |
static inline uint32_t aria_p1( uint32_t x ) |
{ |
uint32_t r; |
__asm( "rev16 r, x" ); |
return( r ); |
} |
#define ARIA_P1 aria_p1 |
#endif |
#endif /* arm */ |
#if defined(__GNUC__) && \ |
defined(__i386__) || defined(__amd64__) || defined( __x86_64__) |
/* I couldn't find an Intel equivalent of rev16, so two instructions */ |
#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) ) |
#endif /* x86 gnuc */ |
#endif /* MBEDTLS_HAVE_ASM && GNUC */ |
#if !defined(ARIA_P1) |
#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) |
#endif |
/* |
* modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits |
* |
* This is submatrix P2 in [1] Appendix B.1 |
* |
* Common compilers will translate this to a single instruction. |
*/ |
#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) |
/* |
* modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness |
* |
* This is submatrix P3 in [1] Appendix B.1 |
* |
* Some compilers fail to translate this to a single instruction, |
* so let's provide asm versions for common platforms with C fallback. |
*/ |
#if defined(MBEDTLS_HAVE_ASM) |
#if defined(__arm__) /* rev available from v6 up */ |
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ |
#if defined(__GNUC__) && \ |
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ |
__ARM_ARCH >= 6 |
static inline uint32_t aria_p3( uint32_t x ) |
{ |
uint32_t r; |
__asm( "rev %0, %1" : "=l" (r) : "l" (x) ); |
return( r ); |
} |
#define ARIA_P3 aria_p3 |
#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ |
( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) |
static inline uint32_t aria_p3( uint32_t x ) |
{ |
uint32_t r; |
__asm( "rev r, x" ); |
return( r ); |
} |
#define ARIA_P3 aria_p3 |
#endif |
#endif /* arm */ |
#if defined(__GNUC__) && \ |
defined(__i386__) || defined(__amd64__) || defined( __x86_64__) |
static inline uint32_t aria_p3( uint32_t x ) |
{ |
__asm( "bswap %0" : "=r" (x) : "0" (x) ); |
return( x ); |
} |
#define ARIA_P3 aria_p3 |
#endif /* x86 gnuc */ |
#endif /* MBEDTLS_HAVE_ASM && GNUC */ |
#if !defined(ARIA_P3) |
#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) ) |
#endif |
/* |
* ARIA Affine Transform |
* (a, b, c, d) = state in/out |
* |
* If we denote the first byte of input by 0, ..., the last byte by f, |
* then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. |
* |
* Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple |
* rearrangements on adjacent pairs, output is: |
* |
* a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe |
* = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd |
* b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd |
* = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc |
* c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe |
* = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc |
* d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef |
* = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef |
* |
* Note: another presentation of the A transform can be found as the first |
* half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. |
* The implementation below uses only P1 and P2 as they are sufficient. |
*/ |
static inline void aria_a( uint32_t *a, uint32_t *b, |
uint32_t *c, uint32_t *d ) |
{ |
uint32_t ta, tb, tc; |
ta = *b; // 4567 |
*b = *a; // 0123 |
*a = ARIA_P2( ta ); // 6745 |
tb = ARIA_P2( *d ); // efcd |
*d = ARIA_P1( *c ); // 98ba |
*c = ARIA_P1( tb ); // fedc |
ta ^= *d; // 4567+98ba |
tc = ARIA_P2( *b ); // 2301 |
ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc |
tb ^= ARIA_P2( *d ); // ba98+efcd |
tc ^= ARIA_P1( *a ); // 2301+7654 |
*b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT |
tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc |
*a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT |
ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe |
*d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT |
tc = ARIA_P2( tc ); // 0123+5476 |
*c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT |
} |
/* |
* ARIA Substitution Layer SL1 / SL2 |
* (a, b, c, d) = state in/out |
* (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) |
* |
* By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 |
* By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 |
*/ |
static inline void aria_sl( uint32_t *a, uint32_t *b, |
uint32_t *c, uint32_t *d, |
const uint8_t sa[256], const uint8_t sb[256], |
const uint8_t sc[256], const uint8_t sd[256] ) |
{ |
*a = ( (uint32_t) sa[ *a & 0xFF] ) ^ |
(((uint32_t) sb[(*a >> 8) & 0xFF]) << 8) ^ |
(((uint32_t) sc[(*a >> 16) & 0xFF]) << 16) ^ |
(((uint32_t) sd[ *a >> 24 ]) << 24); |
*b = ( (uint32_t) sa[ *b & 0xFF] ) ^ |
(((uint32_t) sb[(*b >> 8) & 0xFF]) << 8) ^ |
(((uint32_t) sc[(*b >> 16) & 0xFF]) << 16) ^ |
(((uint32_t) sd[ *b >> 24 ]) << 24); |
*c = ( (uint32_t) sa[ *c & 0xFF] ) ^ |
(((uint32_t) sb[(*c >> 8) & 0xFF]) << 8) ^ |
(((uint32_t) sc[(*c >> 16) & 0xFF]) << 16) ^ |
(((uint32_t) sd[ *c >> 24 ]) << 24); |
*d = ( (uint32_t) sa[ *d & 0xFF] ) ^ |
(((uint32_t) sb[(*d >> 8) & 0xFF]) << 8) ^ |
(((uint32_t) sc[(*d >> 16) & 0xFF]) << 16) ^ |
(((uint32_t) sd[ *d >> 24 ]) << 24); |
} |
/* |
* S-Boxes |
*/ |
static const uint8_t aria_sb1[256] = |
{ |
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, |
0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, |
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, |
0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, |
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, |
0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, |
0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, |
0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, |
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, |
0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, |
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, |
0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, |
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, |
0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, |
0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, |
0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, |
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, |
0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, |
0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, |
0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, |
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, |
0xB0, 0x54, 0xBB, 0x16 |
}; |
static const uint8_t aria_sb2[256] = |
{ |
0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, |
0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, |
0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, |
0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, |
0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, |
0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, |
0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, |
0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, |
0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, |
0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, |
0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, |
0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, |
0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, |
0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, |
0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, |
0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, |
0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, |
0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, |
0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, |
0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, |
0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, |
0xAF, 0xBA, 0xB5, 0x81 |
}; |
static const uint8_t aria_is1[256] = |
{ |
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, |
0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, |
0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, |
0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, |
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, |
0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, |
0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, |
0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, |
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, |
0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, |
0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, |
0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, |
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, |
0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, |
0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, |
0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, |
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, |
0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, |
0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, |
0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, |
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, |
0x55, 0x21, 0x0C, 0x7D |
}; |
static const uint8_t aria_is2[256] = |
{ |
0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, |
0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, |
0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, |
0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, |
0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, |
0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, |
0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, |
0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, |
0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, |
0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, |
0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, |
0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, |
0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, |
0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, |
0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, |
0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, |
0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, |
0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, |
0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, |
0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, |
0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, |
0x03, 0xA2, 0xAC, 0x60 |
}; |
/* |
* Helper for key schedule: r = FO( p, k ) ^ x |
*/ |
static void aria_fo_xor( uint32_t r[4], const uint32_t p[4], |
const uint32_t k[4], const uint32_t x[4] ) |
{ |
uint32_t a, b, c, d; |
a = p[0] ^ k[0]; |
b = p[1] ^ k[1]; |
c = p[2] ^ k[2]; |
d = p[3] ^ k[3]; |
aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); |
aria_a( &a, &b, &c, &d ); |
r[0] = a ^ x[0]; |
r[1] = b ^ x[1]; |
r[2] = c ^ x[2]; |
r[3] = d ^ x[3]; |
} |
/* |
* Helper for key schedule: r = FE( p, k ) ^ x |
*/ |
static void aria_fe_xor( uint32_t r[4], const uint32_t p[4], |
const uint32_t k[4], const uint32_t x[4] ) |
{ |
uint32_t a, b, c, d; |
a = p[0] ^ k[0]; |
b = p[1] ^ k[1]; |
c = p[2] ^ k[2]; |
d = p[3] ^ k[3]; |
aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); |
aria_a( &a, &b, &c, &d ); |
r[0] = a ^ x[0]; |
r[1] = b ^ x[1]; |
r[2] = c ^ x[2]; |
r[3] = d ^ x[3]; |
} |
/* |
* Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. |
* |
* We chose to store bytes into 32-bit words in little-endian format (see |
* GET/PUT_UINT32_LE) so we need to reverse bytes here. |
*/ |
static void aria_rot128( uint32_t r[4], const uint32_t a[4], |
const uint32_t b[4], uint8_t n ) |
{ |
uint8_t i, j; |
uint32_t t, u; |
const uint8_t n1 = n % 32; // bit offset |
const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset |
j = ( n / 32 ) % 4; // initial word offset |
t = ARIA_P3( b[j] ); // big endian |
for( i = 0; i < 4; i++ ) |
{ |
j = ( j + 1 ) % 4; // get next word, big endian |
u = ARIA_P3( b[j] ); |
t <<= n1; // rotate |
t |= u >> n2; |
t = ARIA_P3( t ); // back to little endian |
r[i] = a[i] ^ t; // store |
t = u; // move to next word |
} |
} |
/* |
* Set encryption key |
*/ |
int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, |
const unsigned char *key, unsigned int keybits ) |
{ |
/* round constant masks */ |
const uint32_t rc[3][4] = |
{ |
{ 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, |
{ 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, |
{ 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } |
}; |
int i; |
uint32_t w[4][4], *w2; |
ARIA_VALIDATE_RET( ctx != NULL ); |
ARIA_VALIDATE_RET( key != NULL ); |
if( keybits != 128 && keybits != 192 && keybits != 256 ) |
return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); |
/* Copy key to W0 (and potential remainder to W1) */ |
GET_UINT32_LE( w[0][0], key, 0 ); |
GET_UINT32_LE( w[0][1], key, 4 ); |
GET_UINT32_LE( w[0][2], key, 8 ); |
GET_UINT32_LE( w[0][3], key, 12 ); |
memset( w[1], 0, 16 ); |
if( keybits >= 192 ) |
{ |
GET_UINT32_LE( w[1][0], key, 16 ); // 192 bit key |
GET_UINT32_LE( w[1][1], key, 20 ); |
} |
if( keybits == 256 ) |
{ |
GET_UINT32_LE( w[1][2], key, 24 ); // 256 bit key |
GET_UINT32_LE( w[1][3], key, 28 ); |
} |
i = ( keybits - 128 ) >> 6; // index: 0, 1, 2 |
ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 |
aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR |
i = i < 2 ? i + 1 : 0; |
aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0 |
i = i < 2 ? i + 1 : 0; |
aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1 |
for( i = 0; i < 4; i++ ) // create round keys |
{ |
w2 = w[(i + 1) & 3]; |
aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 ); |
aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 ); |
aria_rot128( ctx->rk[i + 8], w[i], w2, 61 ); |
aria_rot128( ctx->rk[i + 12], w[i], w2, 31 ); |
} |
aria_rot128( ctx->rk[16], w[0], w[1], 19 ); |
/* w holds enough info to reconstruct the round keys */ |
mbedtls_platform_zeroize( w, sizeof( w ) ); |
return( 0 ); |
} |
/* |
* Set decryption key |
*/ |
int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, |
const unsigned char *key, unsigned int keybits ) |
{ |
int i, j, k, ret; |
ARIA_VALIDATE_RET( ctx != NULL ); |
ARIA_VALIDATE_RET( key != NULL ); |
ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); |
if( ret != 0 ) |
return( ret ); |
/* flip the order of round keys */ |
for( i = 0, j = ctx->nr; i < j; i++, j-- ) |
{ |
for( k = 0; k < 4; k++ ) |
{ |
uint32_t t = ctx->rk[i][k]; |
ctx->rk[i][k] = ctx->rk[j][k]; |
ctx->rk[j][k] = t; |
} |
} |
/* apply affine transform to middle keys */ |
for( i = 1; i < ctx->nr; i++ ) |
{ |
aria_a( &ctx->rk[i][0], &ctx->rk[i][1], |
&ctx->rk[i][2], &ctx->rk[i][3] ); |
} |
return( 0 ); |
} |
/* |
* Encrypt a block |
*/ |
int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, |
const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], |
unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ) |
{ |
int i; |
uint32_t a, b, c, d; |
ARIA_VALIDATE_RET( ctx != NULL ); |
ARIA_VALIDATE_RET( input != NULL ); |
ARIA_VALIDATE_RET( output != NULL ); |
GET_UINT32_LE( a, input, 0 ); |
GET_UINT32_LE( b, input, 4 ); |
GET_UINT32_LE( c, input, 8 ); |
GET_UINT32_LE( d, input, 12 ); |
i = 0; |
while( 1 ) |
{ |
a ^= ctx->rk[i][0]; |
b ^= ctx->rk[i][1]; |
c ^= ctx->rk[i][2]; |
d ^= ctx->rk[i][3]; |
i++; |
aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); |
aria_a( &a, &b, &c, &d ); |
a ^= ctx->rk[i][0]; |
b ^= ctx->rk[i][1]; |
c ^= ctx->rk[i][2]; |
d ^= ctx->rk[i][3]; |
i++; |
aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); |
if( i >= ctx->nr ) |
break; |
aria_a( &a, &b, &c, &d ); |
} |
/* final key mixing */ |
a ^= ctx->rk[i][0]; |
b ^= ctx->rk[i][1]; |
c ^= ctx->rk[i][2]; |
d ^= ctx->rk[i][3]; |
PUT_UINT32_LE( a, output, 0 ); |
PUT_UINT32_LE( b, output, 4 ); |
PUT_UINT32_LE( c, output, 8 ); |
PUT_UINT32_LE( d, output, 12 ); |
return( 0 ); |
} |
/* Initialize context */ |
void mbedtls_aria_init( mbedtls_aria_context *ctx ) |
{ |
ARIA_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_aria_context ) ); |
} |
/* Clear context */ |
void mbedtls_aria_free( mbedtls_aria_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* ARIA-CBC buffer encryption/decryption |
*/ |
int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int i; |
unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; |
ARIA_VALIDATE_RET( ctx != NULL ); |
ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || |
mode == MBEDTLS_ARIA_DECRYPT ); |
ARIA_VALIDATE_RET( length == 0 || input != NULL ); |
ARIA_VALIDATE_RET( length == 0 || output != NULL ); |
ARIA_VALIDATE_RET( iv != NULL ); |
if( length % MBEDTLS_ARIA_BLOCKSIZE ) |
return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); |
if( mode == MBEDTLS_ARIA_DECRYPT ) |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE ); |
mbedtls_aria_crypt_ecb( ctx, input, output ); |
for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE ); |
input += MBEDTLS_ARIA_BLOCKSIZE; |
output += MBEDTLS_ARIA_BLOCKSIZE; |
length -= MBEDTLS_ARIA_BLOCKSIZE; |
} |
} |
else |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
mbedtls_aria_crypt_ecb( ctx, output, output ); |
memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE ); |
input += MBEDTLS_ARIA_BLOCKSIZE; |
output += MBEDTLS_ARIA_BLOCKSIZE; |
length -= MBEDTLS_ARIA_BLOCKSIZE; |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
/* |
* ARIA-CFB128 buffer encryption/decryption |
*/ |
int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, |
int mode, |
size_t length, |
size_t *iv_off, |
unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], |
const unsigned char *input, |
unsigned char *output ) |
{ |
unsigned char c; |
size_t n; |
ARIA_VALIDATE_RET( ctx != NULL ); |
ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || |
mode == MBEDTLS_ARIA_DECRYPT ); |
ARIA_VALIDATE_RET( length == 0 || input != NULL ); |
ARIA_VALIDATE_RET( length == 0 || output != NULL ); |
ARIA_VALIDATE_RET( iv != NULL ); |
ARIA_VALIDATE_RET( iv_off != NULL ); |
n = *iv_off; |
/* An overly large value of n can lead to an unlimited |
* buffer overflow. Therefore, guard against this |
* outside of parameter validation. */ |
if( n >= MBEDTLS_ARIA_BLOCKSIZE ) |
return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); |
if( mode == MBEDTLS_ARIA_DECRYPT ) |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_aria_crypt_ecb( ctx, iv, iv ); |
c = *input++; |
*output++ = c ^ iv[n]; |
iv[n] = c; |
n = ( n + 1 ) & 0x0F; |
} |
} |
else |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_aria_crypt_ecb( ctx, iv, iv ); |
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); |
n = ( n + 1 ) & 0x0F; |
} |
} |
*iv_off = n; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* ARIA-CTR buffer encryption/decryption |
*/ |
int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, |
size_t length, |
size_t *nc_off, |
unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], |
unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c, i; |
size_t n; |
ARIA_VALIDATE_RET( ctx != NULL ); |
ARIA_VALIDATE_RET( length == 0 || input != NULL ); |
ARIA_VALIDATE_RET( length == 0 || output != NULL ); |
ARIA_VALIDATE_RET( nonce_counter != NULL ); |
ARIA_VALIDATE_RET( stream_block != NULL ); |
ARIA_VALIDATE_RET( nc_off != NULL ); |
n = *nc_off; |
/* An overly large value of n can lead to an unlimited |
* buffer overflow. Therefore, guard against this |
* outside of parameter validation. */ |
if( n >= MBEDTLS_ARIA_BLOCKSIZE ) |
return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); |
while( length-- ) |
{ |
if( n == 0 ) { |
mbedtls_aria_crypt_ecb( ctx, nonce_counter, |
stream_block ); |
for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- ) |
if( ++nonce_counter[i - 1] != 0 ) |
break; |
} |
c = *input++; |
*output++ = (unsigned char)( c ^ stream_block[n] ); |
n = ( n + 1 ) & 0x0F; |
} |
*nc_off = n; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#endif /* !MBEDTLS_ARIA_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* Basic ARIA ECB test vectors from RFC 5794 |
*/ |
static const uint8_t aria_test1_ecb_key[32] = // test key |
{ |
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit |
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit |
}; |
static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext |
{ |
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all |
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes |
}; |
static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext |
{ |
{ 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit |
0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, |
{ 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit |
0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, |
{ 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit |
0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } |
}; |
/* |
* Mode tests from "Test Vectors for ARIA" Version 1.0 |
* http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf |
*/ |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ |
defined(MBEDTLS_CIPHER_MODE_CTR)) |
static const uint8_t aria_test2_key[32] = |
{ |
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit |
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, |
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit |
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit |
}; |
static const uint8_t aria_test2_pt[48] = |
{ |
0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all |
0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, |
0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, |
0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, |
0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, |
0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, |
}; |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) |
static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = |
{ |
0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB |
0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV |
}; |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext |
{ |
{ 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key |
0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, |
0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, |
0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, |
0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, |
0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, |
{ 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key |
0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, |
0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, |
0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, |
0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, |
0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, |
{ 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key |
0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, |
0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, |
0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, |
0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, |
0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext |
{ |
{ 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key |
0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, |
0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, |
0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, |
0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, |
0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, |
{ 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key |
0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, |
0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, |
0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, |
0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, |
0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, |
{ 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key |
0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, |
0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, |
0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, |
0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, |
0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext |
{ |
{ 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key |
0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, |
0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, |
0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, |
0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, |
0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, |
{ 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key |
0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, |
0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, |
0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, |
0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, |
0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, |
{ 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key |
0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, |
0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, |
0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, |
0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, |
0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#define ARIA_SELF_TEST_IF_FAIL \ |
{ \ |
if( verbose ) \ |
mbedtls_printf( "failed\n" ); \ |
return( 1 ); \ |
} else { \ |
if( verbose ) \ |
mbedtls_printf( "passed\n" ); \ |
} |
/* |
* Checkup routine |
*/ |
int mbedtls_aria_self_test( int verbose ) |
{ |
int i; |
uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; |
mbedtls_aria_context ctx; |
#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) |
size_t j; |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ |
defined(MBEDTLS_CIPHER_MODE_CFB) || \ |
defined(MBEDTLS_CIPHER_MODE_CTR)) |
uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; |
#endif |
/* |
* Test set 1 |
*/ |
for( i = 0; i < 3; i++ ) |
{ |
/* test ECB encryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); |
mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); |
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); |
if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
/* test ECB decryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); |
mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); |
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); |
if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
} |
if( verbose ) |
mbedtls_printf( "\n" ); |
/* |
* Test set 2 |
*/ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
for( i = 0; i < 3; i++ ) |
{ |
/* Test CBC encryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); |
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); |
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); |
memset( buf, 0x55, sizeof( buf ) ); |
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, |
aria_test2_pt, buf ); |
if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
/* Test CBC decryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); |
mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); |
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); |
memset( buf, 0xAA, sizeof( buf ) ); |
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, |
aria_test2_cbc_ct[i], buf ); |
if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
} |
if( verbose ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
for( i = 0; i < 3; i++ ) |
{ |
/* Test CFB encryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); |
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); |
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); |
memset( buf, 0x55, sizeof( buf ) ); |
j = 0; |
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, |
aria_test2_pt, buf ); |
if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
/* Test CFB decryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); |
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); |
memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); |
memset( buf, 0xAA, sizeof( buf ) ); |
j = 0; |
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, |
iv, aria_test2_cfb_ct[i], buf ); |
if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
} |
if( verbose ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
for( i = 0; i < 3; i++ ) |
{ |
/* Test CTR encryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); |
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); |
memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 |
memset( buf, 0x55, sizeof( buf ) ); |
j = 0; |
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, |
aria_test2_pt, buf ); |
if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
/* Test CTR decryption */ |
if( verbose ) |
mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); |
mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); |
memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 |
memset( buf, 0xAA, sizeof( buf ) ); |
j = 0; |
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, |
aria_test2_ctr_ct[i], buf ); |
if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) |
ARIA_SELF_TEST_IF_FAIL; |
} |
if( verbose ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_ARIA_C */ |
/programs/develop/libraries/kos_mbedtls/library/asn1parse.c |
---|
0,0 → 1,391 |
/* |
* Generic ASN.1 parsing |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ASN1_PARSE_C) |
#include "mbedtls/asn1.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_BIGNUM_C) |
#include "mbedtls/bignum.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
/* |
* ASN.1 DER decoding routines |
*/ |
int mbedtls_asn1_get_len( unsigned char **p, |
const unsigned char *end, |
size_t *len ) |
{ |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
if( ( **p & 0x80 ) == 0 ) |
*len = *(*p)++; |
else |
{ |
switch( **p & 0x7F ) |
{ |
case 1: |
if( ( end - *p ) < 2 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
*len = (*p)[1]; |
(*p) += 2; |
break; |
case 2: |
if( ( end - *p ) < 3 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
*len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; |
(*p) += 3; |
break; |
case 3: |
if( ( end - *p ) < 4 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
*len = ( (size_t)(*p)[1] << 16 ) | |
( (size_t)(*p)[2] << 8 ) | (*p)[3]; |
(*p) += 4; |
break; |
case 4: |
if( ( end - *p ) < 5 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
*len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | |
( (size_t)(*p)[3] << 8 ) | (*p)[4]; |
(*p) += 5; |
break; |
default: |
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
} |
} |
if( *len > (size_t) ( end - *p ) ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
return( 0 ); |
} |
int mbedtls_asn1_get_tag( unsigned char **p, |
const unsigned char *end, |
size_t *len, int tag ) |
{ |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
if( **p != tag ) |
return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
(*p)++; |
return( mbedtls_asn1_get_len( p, end, len ) ); |
} |
int mbedtls_asn1_get_bool( unsigned char **p, |
const unsigned char *end, |
int *val ) |
{ |
int ret; |
size_t len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) |
return( ret ); |
if( len != 1 ) |
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
*val = ( **p != 0 ) ? 1 : 0; |
(*p)++; |
return( 0 ); |
} |
int mbedtls_asn1_get_int( unsigned char **p, |
const unsigned char *end, |
int *val ) |
{ |
int ret; |
size_t len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) |
return( ret ); |
if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) |
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
*val = 0; |
while( len-- > 0 ) |
{ |
*val = ( *val << 8 ) | **p; |
(*p)++; |
} |
return( 0 ); |
} |
#if defined(MBEDTLS_BIGNUM_C) |
int mbedtls_asn1_get_mpi( unsigned char **p, |
const unsigned char *end, |
mbedtls_mpi *X ) |
{ |
int ret; |
size_t len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) |
return( ret ); |
ret = mbedtls_mpi_read_binary( X, *p, len ); |
*p += len; |
return( ret ); |
} |
#endif /* MBEDTLS_BIGNUM_C */ |
int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, |
mbedtls_asn1_bitstring *bs) |
{ |
int ret; |
/* Certificate type is a single byte bitstring */ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) |
return( ret ); |
/* Check length, subtract one for actual bit string length */ |
if( bs->len < 1 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
bs->len -= 1; |
/* Get number of unused bits, ensure unused bits <= 7 */ |
bs->unused_bits = **p; |
if( bs->unused_bits > 7 ) |
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
(*p)++; |
/* Get actual bitstring */ |
bs->p = *p; |
*p += bs->len; |
if( *p != end ) |
return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* Get a bit string without unused bits |
*/ |
int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, |
size_t *len ) |
{ |
int ret; |
if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) |
return( ret ); |
if( (*len)-- < 2 || *(*p)++ != 0 ) |
return( MBEDTLS_ERR_ASN1_INVALID_DATA ); |
return( 0 ); |
} |
/* |
* Parses and splits an ASN.1 "SEQUENCE OF <tag>" |
*/ |
int mbedtls_asn1_get_sequence_of( unsigned char **p, |
const unsigned char *end, |
mbedtls_asn1_sequence *cur, |
int tag) |
{ |
int ret; |
size_t len; |
mbedtls_asn1_buf *buf; |
/* Get main sequence tag */ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( ret ); |
if( *p + len != end ) |
return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
while( *p < end ) |
{ |
buf = &(cur->buf); |
buf->tag = **p; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) |
return( ret ); |
buf->p = *p; |
*p += buf->len; |
/* Allocate and assign next pointer */ |
if( *p < end ) |
{ |
cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, |
sizeof( mbedtls_asn1_sequence ) ); |
if( cur->next == NULL ) |
return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); |
cur = cur->next; |
} |
} |
/* Set final sequence entry's next pointer to NULL */ |
cur->next = NULL; |
if( *p != end ) |
return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
int mbedtls_asn1_get_alg( unsigned char **p, |
const unsigned char *end, |
mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) |
{ |
int ret; |
size_t len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( ret ); |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
alg->tag = **p; |
end = *p + len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) |
return( ret ); |
alg->p = *p; |
*p += alg->len; |
if( *p == end ) |
{ |
mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); |
return( 0 ); |
} |
params->tag = **p; |
(*p)++; |
if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) |
return( ret ); |
params->p = *p; |
*p += params->len; |
if( *p != end ) |
return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
int mbedtls_asn1_get_alg_null( unsigned char **p, |
const unsigned char *end, |
mbedtls_asn1_buf *alg ) |
{ |
int ret; |
mbedtls_asn1_buf params; |
memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); |
if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) |
return( ret ); |
if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) |
return( MBEDTLS_ERR_ASN1_INVALID_DATA ); |
return( 0 ); |
} |
void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) |
{ |
if( cur == NULL ) |
return; |
mbedtls_free( cur->oid.p ); |
mbedtls_free( cur->val.p ); |
mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); |
} |
void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) |
{ |
mbedtls_asn1_named_data *cur; |
while( ( cur = *head ) != NULL ) |
{ |
*head = cur->next; |
mbedtls_asn1_free_named_data( cur ); |
mbedtls_free( cur ); |
} |
} |
mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, |
const char *oid, size_t len ) |
{ |
while( list != NULL ) |
{ |
if( list->oid.len == len && |
memcmp( list->oid.p, oid, len ) == 0 ) |
{ |
break; |
} |
list = list->next; |
} |
return( list ); |
} |
#endif /* MBEDTLS_ASN1_PARSE_C */ |
/programs/develop/libraries/kos_mbedtls/library/asn1write.c |
---|
0,0 → 1,423 |
/* |
* ASN.1 buffer writing functionality |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ASN1_WRITE_C) |
#include "mbedtls/asn1write.h" |
#include <string.h> |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) |
{ |
if( len < 0x80 ) |
{ |
if( *p - start < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = (unsigned char) len; |
return( 1 ); |
} |
if( len <= 0xFF ) |
{ |
if( *p - start < 2 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = (unsigned char) len; |
*--(*p) = 0x81; |
return( 2 ); |
} |
if( len <= 0xFFFF ) |
{ |
if( *p - start < 3 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = ( len ) & 0xFF; |
*--(*p) = ( len >> 8 ) & 0xFF; |
*--(*p) = 0x82; |
return( 3 ); |
} |
if( len <= 0xFFFFFF ) |
{ |
if( *p - start < 4 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = ( len ) & 0xFF; |
*--(*p) = ( len >> 8 ) & 0xFF; |
*--(*p) = ( len >> 16 ) & 0xFF; |
*--(*p) = 0x83; |
return( 4 ); |
} |
#if SIZE_MAX > 0xFFFFFFFF |
if( len <= 0xFFFFFFFF ) |
#endif |
{ |
if( *p - start < 5 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = ( len ) & 0xFF; |
*--(*p) = ( len >> 8 ) & 0xFF; |
*--(*p) = ( len >> 16 ) & 0xFF; |
*--(*p) = ( len >> 24 ) & 0xFF; |
*--(*p) = 0x84; |
return( 5 ); |
} |
#if SIZE_MAX > 0xFFFFFFFF |
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
#endif |
} |
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) |
{ |
if( *p - start < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = tag; |
return( 1 ); |
} |
int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, |
const unsigned char *buf, size_t size ) |
{ |
size_t len = 0; |
if( *p < start || (size_t)( *p - start ) < size ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
len = size; |
(*p) -= len; |
memcpy( *p, buf, len ); |
return( (int) len ); |
} |
#if defined(MBEDTLS_BIGNUM_C) |
int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) |
{ |
int ret; |
size_t len = 0; |
// Write the MPI |
// |
len = mbedtls_mpi_size( X ); |
if( *p < start || (size_t)( *p - start ) < len ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
(*p) -= len; |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); |
// DER format assumes 2s complement for numbers, so the leftmost bit |
// should be 0 for positive numbers and 1 for negative numbers. |
// |
if( X->s ==1 && **p & 0x80 ) |
{ |
if( *p - start < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = 0x00; |
len += 1; |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); |
ret = (int) len; |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_BIGNUM_C */ |
int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) |
{ |
int ret; |
size_t len = 0; |
// Write NULL |
// |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); |
return( (int) len ); |
} |
int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, |
const char *oid, size_t oid_len ) |
{ |
int ret; |
size_t len = 0; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, |
(const unsigned char *) oid, oid_len ) ); |
MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); |
return( (int) len ); |
} |
int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, |
const char *oid, size_t oid_len, |
size_t par_len ) |
{ |
int ret; |
size_t len = 0; |
if( par_len == 0 ) |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); |
else |
len += par_len; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); |
return( (int) len ); |
} |
int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) |
{ |
int ret; |
size_t len = 0; |
if( *p - start < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = (boolean) ? 255 : 0; |
len++; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); |
return( (int) len ); |
} |
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) |
{ |
int ret; |
size_t len = 0; |
if( *p - start < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
len += 1; |
*--(*p) = val; |
if( val > 0 && **p & 0x80 ) |
{ |
if( *p - start < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = 0x00; |
len += 1; |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); |
return( (int) len ); |
} |
int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, |
const char *text, size_t text_len ) |
{ |
int ret; |
size_t len = 0; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, |
(const unsigned char *) text, text_len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); |
return( (int) len ); |
} |
int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, |
const char *text, size_t text_len ) |
{ |
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); |
} |
int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, |
const char *text, size_t text_len ) |
{ |
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); |
} |
int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, |
const char *text, size_t text_len ) |
{ |
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); |
} |
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, |
const unsigned char *buf, size_t bits ) |
{ |
int ret; |
size_t len = 0; |
size_t unused_bits, byte_len; |
byte_len = ( bits + 7 ) / 8; |
unused_bits = ( byte_len * 8 ) - bits; |
if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
len = byte_len + 1; |
/* Write the bitstring. Ensure the unused bits are zeroed */ |
if( byte_len > 0 ) |
{ |
byte_len--; |
*--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); |
( *p ) -= byte_len; |
memcpy( *p, buf, byte_len ); |
} |
/* Write unused bits */ |
*--( *p ) = (unsigned char)unused_bits; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); |
return( (int) len ); |
} |
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, |
const unsigned char *buf, size_t size ) |
{ |
int ret; |
size_t len = 0; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); |
return( (int) len ); |
} |
/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), |
* which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ |
static mbedtls_asn1_named_data *asn1_find_named_data( |
mbedtls_asn1_named_data *list, |
const char *oid, size_t len ) |
{ |
while( list != NULL ) |
{ |
if( list->oid.len == len && |
memcmp( list->oid.p, oid, len ) == 0 ) |
{ |
break; |
} |
list = list->next; |
} |
return( list ); |
} |
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( |
mbedtls_asn1_named_data **head, |
const char *oid, size_t oid_len, |
const unsigned char *val, |
size_t val_len ) |
{ |
mbedtls_asn1_named_data *cur; |
if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) |
{ |
// Add new entry if not present yet based on OID |
// |
cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, |
sizeof(mbedtls_asn1_named_data) ); |
if( cur == NULL ) |
return( NULL ); |
cur->oid.len = oid_len; |
cur->oid.p = mbedtls_calloc( 1, oid_len ); |
if( cur->oid.p == NULL ) |
{ |
mbedtls_free( cur ); |
return( NULL ); |
} |
memcpy( cur->oid.p, oid, oid_len ); |
cur->val.len = val_len; |
cur->val.p = mbedtls_calloc( 1, val_len ); |
if( cur->val.p == NULL ) |
{ |
mbedtls_free( cur->oid.p ); |
mbedtls_free( cur ); |
return( NULL ); |
} |
cur->next = *head; |
*head = cur; |
} |
else if( cur->val.len < val_len ) |
{ |
/* |
* Enlarge existing value buffer if needed |
* Preserve old data until the allocation succeeded, to leave list in |
* a consistent state in case allocation fails. |
*/ |
void *p = mbedtls_calloc( 1, val_len ); |
if( p == NULL ) |
return( NULL ); |
mbedtls_free( cur->val.p ); |
cur->val.p = p; |
cur->val.len = val_len; |
} |
if( val != NULL ) |
memcpy( cur->val.p, val, val_len ); |
return( cur ); |
} |
#endif /* MBEDTLS_ASN1_WRITE_C */ |
/programs/develop/libraries/kos_mbedtls/library/base64.c |
---|
0,0 → 1,295 |
/* |
* RFC 1521 base64 encoding/decoding |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_BASE64_C) |
#include "mbedtls/base64.h" |
#include <stdint.h> |
#if defined(MBEDTLS_SELF_TEST) |
#include <string.h> |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
static const unsigned char base64_enc_map[64] = |
{ |
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', |
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', |
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', |
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', |
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', |
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', |
'8', '9', '+', '/' |
}; |
static const unsigned char base64_dec_map[128] = |
{ |
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, |
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, |
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, |
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, |
127, 127, 127, 62, 127, 127, 127, 63, 52, 53, |
54, 55, 56, 57, 58, 59, 60, 61, 127, 127, |
127, 64, 127, 127, 127, 0, 1, 2, 3, 4, |
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, |
25, 127, 127, 127, 127, 127, 127, 26, 27, 28, |
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, |
49, 50, 51, 127, 127, 127, 127, 127 |
}; |
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ |
/* |
* Encode a buffer into base64 format |
*/ |
int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, |
const unsigned char *src, size_t slen ) |
{ |
size_t i, n; |
int C1, C2, C3; |
unsigned char *p; |
if( slen == 0 ) |
{ |
*olen = 0; |
return( 0 ); |
} |
n = slen / 3 + ( slen % 3 != 0 ); |
if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) |
{ |
*olen = BASE64_SIZE_T_MAX; |
return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); |
} |
n *= 4; |
if( ( dlen < n + 1 ) || ( NULL == dst ) ) |
{ |
*olen = n + 1; |
return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); |
} |
n = ( slen / 3 ) * 3; |
for( i = 0, p = dst; i < n; i += 3 ) |
{ |
C1 = *src++; |
C2 = *src++; |
C3 = *src++; |
*p++ = base64_enc_map[(C1 >> 2) & 0x3F]; |
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; |
*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; |
*p++ = base64_enc_map[C3 & 0x3F]; |
} |
if( i < slen ) |
{ |
C1 = *src++; |
C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; |
*p++ = base64_enc_map[(C1 >> 2) & 0x3F]; |
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; |
if( ( i + 1 ) < slen ) |
*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; |
else *p++ = '='; |
*p++ = '='; |
} |
*olen = p - dst; |
*p = 0; |
return( 0 ); |
} |
/* |
* Decode a base64-formatted buffer |
*/ |
int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, |
const unsigned char *src, size_t slen ) |
{ |
size_t i, n; |
uint32_t j, x; |
unsigned char *p; |
/* First pass: check for validity and get output length */ |
for( i = n = j = 0; i < slen; i++ ) |
{ |
/* Skip spaces before checking for EOL */ |
x = 0; |
while( i < slen && src[i] == ' ' ) |
{ |
++i; |
++x; |
} |
/* Spaces at end of buffer are OK */ |
if( i == slen ) |
break; |
if( ( slen - i ) >= 2 && |
src[i] == '\r' && src[i + 1] == '\n' ) |
continue; |
if( src[i] == '\n' ) |
continue; |
/* Space inside a line is an error */ |
if( x != 0 ) |
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); |
if( src[i] == '=' && ++j > 2 ) |
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); |
if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) |
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); |
if( base64_dec_map[src[i]] < 64 && j != 0 ) |
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); |
n++; |
} |
if( n == 0 ) |
{ |
*olen = 0; |
return( 0 ); |
} |
/* The following expression is to calculate the following formula without |
* risk of integer overflow in n: |
* n = ( ( n * 6 ) + 7 ) >> 3; |
*/ |
n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); |
n -= j; |
if( dst == NULL || dlen < n ) |
{ |
*olen = n; |
return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); |
} |
for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) |
{ |
if( *src == '\r' || *src == '\n' || *src == ' ' ) |
continue; |
j -= ( base64_dec_map[*src] == 64 ); |
x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); |
if( ++n == 4 ) |
{ |
n = 0; |
if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); |
if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); |
if( j > 2 ) *p++ = (unsigned char)( x ); |
} |
} |
*olen = p - dst; |
return( 0 ); |
} |
#if defined(MBEDTLS_SELF_TEST) |
static const unsigned char base64_test_dec[64] = |
{ |
0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, |
0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, |
0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, |
0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, |
0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, |
0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, |
0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, |
0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 |
}; |
static const unsigned char base64_test_enc[] = |
"JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" |
"swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; |
/* |
* Checkup routine |
*/ |
int mbedtls_base64_self_test( int verbose ) |
{ |
size_t len; |
const unsigned char *src; |
unsigned char buffer[128]; |
if( verbose != 0 ) |
mbedtls_printf( " Base64 encoding test: " ); |
src = base64_test_dec; |
if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || |
memcmp( base64_test_enc, buffer, 88 ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n Base64 decoding test: " ); |
src = base64_test_enc; |
if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || |
memcmp( base64_test_dec, buffer, 64 ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_BASE64_C */ |
/programs/develop/libraries/kos_mbedtls/library/bignum.c |
---|
0,0 → 1,2868 |
/* |
* Multi-precision integer library |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The following sources were referenced in the design of this Multi-precision |
* Integer library: |
* |
* [1] Handbook of Applied Cryptography - 1997 |
* Menezes, van Oorschot and Vanstone |
* |
* [2] Multi-Precision Math |
* Tom St Denis |
* https://github.com/libtom/libtommath/blob/develop/tommath.pdf |
* |
* [3] GNU Multi-Precision Arithmetic Library |
* https://gmplib.org/manual/index.html |
* |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_BIGNUM_C) |
#include "mbedtls/bignum.h" |
#include "mbedtls/bn_mul.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#include <stdlib.h> |
#define mbedtls_printf printf |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#define MPI_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) |
#define MPI_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ |
#define biL (ciL << 3) /* bits in limb */ |
#define biH (ciL << 2) /* half limb size */ |
#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ |
/* |
* Convert between bits/chars and number of limbs |
* Divide first in order to avoid potential overflows |
*/ |
#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) |
#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) |
/* Implementation that should never be optimized out by the compiler */ |
static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) |
{ |
mbedtls_platform_zeroize( v, ciL * n ); |
} |
/* |
* Initialize one MPI |
*/ |
void mbedtls_mpi_init( mbedtls_mpi *X ) |
{ |
MPI_VALIDATE( X != NULL ); |
X->s = 1; |
X->n = 0; |
X->p = NULL; |
} |
/* |
* Unallocate one MPI |
*/ |
void mbedtls_mpi_free( mbedtls_mpi *X ) |
{ |
if( X == NULL ) |
return; |
if( X->p != NULL ) |
{ |
mbedtls_mpi_zeroize( X->p, X->n ); |
mbedtls_free( X->p ); |
} |
X->s = 1; |
X->n = 0; |
X->p = NULL; |
} |
/* |
* Enlarge to the specified number of limbs |
*/ |
int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) |
{ |
mbedtls_mpi_uint *p; |
MPI_VALIDATE_RET( X != NULL ); |
if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) |
return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); |
if( X->n < nblimbs ) |
{ |
if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) |
return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); |
if( X->p != NULL ) |
{ |
memcpy( p, X->p, X->n * ciL ); |
mbedtls_mpi_zeroize( X->p, X->n ); |
mbedtls_free( X->p ); |
} |
X->n = nblimbs; |
X->p = p; |
} |
return( 0 ); |
} |
/* |
* Resize down as much as possible, |
* while keeping at least the specified number of limbs |
*/ |
int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) |
{ |
mbedtls_mpi_uint *p; |
size_t i; |
MPI_VALIDATE_RET( X != NULL ); |
if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) |
return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); |
/* Actually resize up if there are currently fewer than nblimbs limbs. */ |
if( X->n <= nblimbs ) |
return( mbedtls_mpi_grow( X, nblimbs ) ); |
/* After this point, then X->n > nblimbs and in particular X->n > 0. */ |
for( i = X->n - 1; i > 0; i-- ) |
if( X->p[i] != 0 ) |
break; |
i++; |
if( i < nblimbs ) |
i = nblimbs; |
if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) |
return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); |
if( X->p != NULL ) |
{ |
memcpy( p, X->p, i * ciL ); |
mbedtls_mpi_zeroize( X->p, X->n ); |
mbedtls_free( X->p ); |
} |
X->n = i; |
X->p = p; |
return( 0 ); |
} |
/* |
* Copy the contents of Y into X |
*/ |
int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) |
{ |
int ret = 0; |
size_t i; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( Y != NULL ); |
if( X == Y ) |
return( 0 ); |
if( Y->n == 0 ) |
{ |
mbedtls_mpi_free( X ); |
return( 0 ); |
} |
for( i = Y->n - 1; i > 0; i-- ) |
if( Y->p[i] != 0 ) |
break; |
i++; |
X->s = Y->s; |
if( X->n < i ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); |
} |
else |
{ |
memset( X->p + i, 0, ( X->n - i ) * ciL ); |
} |
memcpy( X->p, Y->p, i * ciL ); |
cleanup: |
return( ret ); |
} |
/* |
* Swap the contents of X and Y |
*/ |
void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) |
{ |
mbedtls_mpi T; |
MPI_VALIDATE( X != NULL ); |
MPI_VALIDATE( Y != NULL ); |
memcpy( &T, X, sizeof( mbedtls_mpi ) ); |
memcpy( X, Y, sizeof( mbedtls_mpi ) ); |
memcpy( Y, &T, sizeof( mbedtls_mpi ) ); |
} |
/* |
* Conditionally assign X = Y, without leaking information |
* about whether the assignment was made or not. |
* (Leaking information about the respective sizes of X and Y is ok however.) |
*/ |
int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) |
{ |
int ret = 0; |
size_t i; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( Y != NULL ); |
/* make sure assign is 0 or 1 in a time-constant manner */ |
assign = (assign | (unsigned char)-assign) >> 7; |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); |
X->s = X->s * ( 1 - assign ) + Y->s * assign; |
for( i = 0; i < Y->n; i++ ) |
X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; |
for( ; i < X->n; i++ ) |
X->p[i] *= ( 1 - assign ); |
cleanup: |
return( ret ); |
} |
/* |
* Conditionally swap X and Y, without leaking information |
* about whether the swap was made or not. |
* Here it is not ok to simply swap the pointers, which whould lead to |
* different memory access patterns when X and Y are used afterwards. |
*/ |
int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) |
{ |
int ret, s; |
size_t i; |
mbedtls_mpi_uint tmp; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( Y != NULL ); |
if( X == Y ) |
return( 0 ); |
/* make sure swap is 0 or 1 in a time-constant manner */ |
swap = (swap | (unsigned char)-swap) >> 7; |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); |
s = X->s; |
X->s = X->s * ( 1 - swap ) + Y->s * swap; |
Y->s = Y->s * ( 1 - swap ) + s * swap; |
for( i = 0; i < X->n; i++ ) |
{ |
tmp = X->p[i]; |
X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; |
Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; |
} |
cleanup: |
return( ret ); |
} |
/* |
* Set value from integer |
*/ |
int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) |
{ |
int ret; |
MPI_VALIDATE_RET( X != NULL ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); |
memset( X->p, 0, X->n * ciL ); |
X->p[0] = ( z < 0 ) ? -z : z; |
X->s = ( z < 0 ) ? -1 : 1; |
cleanup: |
return( ret ); |
} |
/* |
* Get a specific bit |
*/ |
int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) |
{ |
MPI_VALIDATE_RET( X != NULL ); |
if( X->n * biL <= pos ) |
return( 0 ); |
return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); |
} |
/* Get a specific byte, without range checks. */ |
#define GET_BYTE( X, i ) \ |
( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) |
/* |
* Set a bit to a specific value of 0 or 1 |
*/ |
int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) |
{ |
int ret = 0; |
size_t off = pos / biL; |
size_t idx = pos % biL; |
MPI_VALIDATE_RET( X != NULL ); |
if( val != 0 && val != 1 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
if( X->n * biL <= pos ) |
{ |
if( val == 0 ) |
return( 0 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); |
} |
X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); |
X->p[off] |= (mbedtls_mpi_uint) val << idx; |
cleanup: |
return( ret ); |
} |
/* |
* Return the number of less significant zero-bits |
*/ |
size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) |
{ |
size_t i, j, count = 0; |
MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); |
for( i = 0; i < X->n; i++ ) |
for( j = 0; j < biL; j++, count++ ) |
if( ( ( X->p[i] >> j ) & 1 ) != 0 ) |
return( count ); |
return( 0 ); |
} |
/* |
* Count leading zero bits in a given integer |
*/ |
static size_t mbedtls_clz( const mbedtls_mpi_uint x ) |
{ |
size_t j; |
mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); |
for( j = 0; j < biL; j++ ) |
{ |
if( x & mask ) break; |
mask >>= 1; |
} |
return j; |
} |
/* |
* Return the number of bits |
*/ |
size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) |
{ |
size_t i, j; |
if( X->n == 0 ) |
return( 0 ); |
for( i = X->n - 1; i > 0; i-- ) |
if( X->p[i] != 0 ) |
break; |
j = biL - mbedtls_clz( X->p[i] ); |
return( ( i * biL ) + j ); |
} |
/* |
* Return the total size in bytes |
*/ |
size_t mbedtls_mpi_size( const mbedtls_mpi *X ) |
{ |
return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); |
} |
/* |
* Convert an ASCII character to digit value |
*/ |
static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) |
{ |
*d = 255; |
if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; |
if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; |
if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; |
if( *d >= (mbedtls_mpi_uint) radix ) |
return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); |
return( 0 ); |
} |
/* |
* Import from an ASCII string |
*/ |
int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) |
{ |
int ret; |
size_t i, j, slen, n; |
mbedtls_mpi_uint d; |
mbedtls_mpi T; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( s != NULL ); |
if( radix < 2 || radix > 16 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
mbedtls_mpi_init( &T ); |
slen = strlen( s ); |
if( radix == 16 ) |
{ |
if( slen > MPI_SIZE_T_MAX >> 2 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
n = BITS_TO_LIMBS( slen << 2 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); |
for( i = slen, j = 0; i > 0; i--, j++ ) |
{ |
if( i == 1 && s[i - 1] == '-' ) |
{ |
X->s = -1; |
break; |
} |
MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); |
X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); |
} |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); |
for( i = 0; i < slen; i++ ) |
{ |
if( i == 0 && s[i] == '-' ) |
{ |
X->s = -1; |
continue; |
} |
MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); |
if( X->s == 1 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); |
} |
} |
} |
cleanup: |
mbedtls_mpi_free( &T ); |
return( ret ); |
} |
/* |
* Helper to write the digits high-order first. |
*/ |
static int mpi_write_hlp( mbedtls_mpi *X, int radix, |
char **p, const size_t buflen ) |
{ |
int ret; |
mbedtls_mpi_uint r; |
size_t length = 0; |
char *p_end = *p + buflen; |
do |
{ |
if( length >= buflen ) |
{ |
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); |
/* |
* Write the residue in the current position, as an ASCII character. |
*/ |
if( r < 0xA ) |
*(--p_end) = (char)( '0' + r ); |
else |
*(--p_end) = (char)( 'A' + ( r - 0xA ) ); |
length++; |
} while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); |
memmove( *p, p_end, length ); |
*p += length; |
cleanup: |
return( ret ); |
} |
/* |
* Export into an ASCII string |
*/ |
int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, |
char *buf, size_t buflen, size_t *olen ) |
{ |
int ret = 0; |
size_t n; |
char *p; |
mbedtls_mpi T; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( olen != NULL ); |
MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); |
if( radix < 2 || radix > 16 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ |
if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present |
* `n`. If radix > 4, this might be a strict |
* overapproximation of the number of |
* radix-adic digits needed to present `n`. */ |
if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to |
* present `n`. */ |
n += 1; /* Terminating null byte */ |
n += 1; /* Compensate for the divisions above, which round down `n` |
* in case it's not even. */ |
n += 1; /* Potential '-'-sign. */ |
n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, |
* which always uses an even number of hex-digits. */ |
if( buflen < n ) |
{ |
*olen = n; |
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); |
} |
p = buf; |
mbedtls_mpi_init( &T ); |
if( X->s == -1 ) |
{ |
*p++ = '-'; |
buflen--; |
} |
if( radix == 16 ) |
{ |
int c; |
size_t i, j, k; |
for( i = X->n, k = 0; i > 0; i-- ) |
{ |
for( j = ciL; j > 0; j-- ) |
{ |
c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; |
if( c == 0 && k == 0 && ( i + j ) != 2 ) |
continue; |
*(p++) = "0123456789ABCDEF" [c / 16]; |
*(p++) = "0123456789ABCDEF" [c % 16]; |
k = 1; |
} |
} |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); |
if( T.s == -1 ) |
T.s = 1; |
MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); |
} |
*p++ = '\0'; |
*olen = p - buf; |
cleanup: |
mbedtls_mpi_free( &T ); |
return( ret ); |
} |
#if defined(MBEDTLS_FS_IO) |
/* |
* Read X from an opened file |
*/ |
int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) |
{ |
mbedtls_mpi_uint d; |
size_t slen; |
char *p; |
/* |
* Buffer should have space for (short) label and decimal formatted MPI, |
* newline characters and '\0' |
*/ |
char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( fin != NULL ); |
if( radix < 2 || radix > 16 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
memset( s, 0, sizeof( s ) ); |
if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) |
return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); |
slen = strlen( s ); |
if( slen == sizeof( s ) - 2 ) |
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); |
if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } |
if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } |
p = s + slen; |
while( p-- > s ) |
if( mpi_get_digit( &d, radix, *p ) != 0 ) |
break; |
return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); |
} |
/* |
* Write X into an opened file (or stdout if fout == NULL) |
*/ |
int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) |
{ |
int ret; |
size_t n, slen, plen; |
/* |
* Buffer should have space for (short) label and decimal formatted MPI, |
* newline characters and '\0' |
*/ |
char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; |
MPI_VALIDATE_RET( X != NULL ); |
if( radix < 2 || radix > 16 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
memset( s, 0, sizeof( s ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); |
if( p == NULL ) p = ""; |
plen = strlen( p ); |
slen = strlen( s ); |
s[slen++] = '\r'; |
s[slen++] = '\n'; |
if( fout != NULL ) |
{ |
if( fwrite( p, 1, plen, fout ) != plen || |
fwrite( s, 1, slen, fout ) != slen ) |
return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); |
} |
else |
mbedtls_printf( "%s%s", p, s ); |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_FS_IO */ |
/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint |
* into the storage form used by mbedtls_mpi. */ |
static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) |
{ |
uint8_t i; |
unsigned char *x_ptr; |
mbedtls_mpi_uint tmp = 0; |
for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) |
{ |
tmp <<= CHAR_BIT; |
tmp |= (mbedtls_mpi_uint) *x_ptr; |
} |
return( tmp ); |
} |
static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) |
{ |
#if defined(__BYTE_ORDER__) |
/* Nothing to do on bigendian systems. */ |
#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) |
return( x ); |
#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ |
#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) |
/* For GCC and Clang, have builtins for byte swapping. */ |
#if defined(__GNUC__) && defined(__GNUC_PREREQ) |
#if __GNUC_PREREQ(4,3) |
#define have_bswap |
#endif |
#endif |
#if defined(__clang__) && defined(__has_builtin) |
#if __has_builtin(__builtin_bswap32) && \ |
__has_builtin(__builtin_bswap64) |
#define have_bswap |
#endif |
#endif |
#if defined(have_bswap) |
/* The compiler is hopefully able to statically evaluate this! */ |
switch( sizeof(mbedtls_mpi_uint) ) |
{ |
case 4: |
return( __builtin_bswap32(x) ); |
case 8: |
return( __builtin_bswap64(x) ); |
} |
#endif |
#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ |
#endif /* __BYTE_ORDER__ */ |
/* Fall back to C-based reordering if we don't know the byte order |
* or we couldn't use a compiler-specific builtin. */ |
return( mpi_uint_bigendian_to_host_c( x ) ); |
} |
static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) |
{ |
mbedtls_mpi_uint *cur_limb_left; |
mbedtls_mpi_uint *cur_limb_right; |
if( limbs == 0 ) |
return; |
/* |
* Traverse limbs and |
* - adapt byte-order in each limb |
* - swap the limbs themselves. |
* For that, simultaneously traverse the limbs from left to right |
* and from right to left, as long as the left index is not bigger |
* than the right index (it's not a problem if limbs is odd and the |
* indices coincide in the last iteration). |
*/ |
for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); |
cur_limb_left <= cur_limb_right; |
cur_limb_left++, cur_limb_right-- ) |
{ |
mbedtls_mpi_uint tmp; |
/* Note that if cur_limb_left == cur_limb_right, |
* this code effectively swaps the bytes only once. */ |
tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); |
*cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); |
*cur_limb_right = tmp; |
} |
} |
/* |
* Import X from unsigned binary data, big endian |
*/ |
int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) |
{ |
int ret; |
size_t const limbs = CHARS_TO_LIMBS( buflen ); |
size_t const overhead = ( limbs * ciL ) - buflen; |
unsigned char *Xp; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); |
/* Ensure that target MPI has exactly the necessary number of limbs */ |
if( X->n != limbs ) |
{ |
mbedtls_mpi_free( X ); |
mbedtls_mpi_init( X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); |
/* Avoid calling `memcpy` with NULL source argument, |
* even if buflen is 0. */ |
if( buf != NULL ) |
{ |
Xp = (unsigned char*) X->p; |
memcpy( Xp + overhead, buf, buflen ); |
mpi_bigendian_to_host( X->p, limbs ); |
} |
cleanup: |
return( ret ); |
} |
/* |
* Export X into unsigned binary data, big endian |
*/ |
int mbedtls_mpi_write_binary( const mbedtls_mpi *X, |
unsigned char *buf, size_t buflen ) |
{ |
size_t stored_bytes; |
size_t bytes_to_copy; |
unsigned char *p; |
size_t i; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); |
stored_bytes = X->n * ciL; |
if( stored_bytes < buflen ) |
{ |
/* There is enough space in the output buffer. Write initial |
* null bytes and record the position at which to start |
* writing the significant bytes. In this case, the execution |
* trace of this function does not depend on the value of the |
* number. */ |
bytes_to_copy = stored_bytes; |
p = buf + buflen - stored_bytes; |
memset( buf, 0, buflen - stored_bytes ); |
} |
else |
{ |
/* The output buffer is smaller than the allocated size of X. |
* However X may fit if its leading bytes are zero. */ |
bytes_to_copy = buflen; |
p = buf; |
for( i = bytes_to_copy; i < stored_bytes; i++ ) |
{ |
if( GET_BYTE( X, i ) != 0 ) |
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); |
} |
} |
for( i = 0; i < bytes_to_copy; i++ ) |
p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); |
return( 0 ); |
} |
/* |
* Left-shift: X <<= count |
*/ |
int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) |
{ |
int ret; |
size_t i, v0, t1; |
mbedtls_mpi_uint r0 = 0, r1; |
MPI_VALIDATE_RET( X != NULL ); |
v0 = count / (biL ); |
t1 = count & (biL - 1); |
i = mbedtls_mpi_bitlen( X ) + count; |
if( X->n * biL < i ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); |
ret = 0; |
/* |
* shift by count / limb_size |
*/ |
if( v0 > 0 ) |
{ |
for( i = X->n; i > v0; i-- ) |
X->p[i - 1] = X->p[i - v0 - 1]; |
for( ; i > 0; i-- ) |
X->p[i - 1] = 0; |
} |
/* |
* shift by count % limb_size |
*/ |
if( t1 > 0 ) |
{ |
for( i = v0; i < X->n; i++ ) |
{ |
r1 = X->p[i] >> (biL - t1); |
X->p[i] <<= t1; |
X->p[i] |= r0; |
r0 = r1; |
} |
} |
cleanup: |
return( ret ); |
} |
/* |
* Right-shift: X >>= count |
*/ |
int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) |
{ |
size_t i, v0, v1; |
mbedtls_mpi_uint r0 = 0, r1; |
MPI_VALIDATE_RET( X != NULL ); |
v0 = count / biL; |
v1 = count & (biL - 1); |
if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) |
return mbedtls_mpi_lset( X, 0 ); |
/* |
* shift by count / limb_size |
*/ |
if( v0 > 0 ) |
{ |
for( i = 0; i < X->n - v0; i++ ) |
X->p[i] = X->p[i + v0]; |
for( ; i < X->n; i++ ) |
X->p[i] = 0; |
} |
/* |
* shift by count % limb_size |
*/ |
if( v1 > 0 ) |
{ |
for( i = X->n; i > 0; i-- ) |
{ |
r1 = X->p[i - 1] << (biL - v1); |
X->p[i - 1] >>= v1; |
X->p[i - 1] |= r0; |
r0 = r1; |
} |
} |
return( 0 ); |
} |
/* |
* Compare unsigned values |
*/ |
int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) |
{ |
size_t i, j; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( Y != NULL ); |
for( i = X->n; i > 0; i-- ) |
if( X->p[i - 1] != 0 ) |
break; |
for( j = Y->n; j > 0; j-- ) |
if( Y->p[j - 1] != 0 ) |
break; |
if( i == 0 && j == 0 ) |
return( 0 ); |
if( i > j ) return( 1 ); |
if( j > i ) return( -1 ); |
for( ; i > 0; i-- ) |
{ |
if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); |
if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); |
} |
return( 0 ); |
} |
/* |
* Compare signed values |
*/ |
int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) |
{ |
size_t i, j; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( Y != NULL ); |
for( i = X->n; i > 0; i-- ) |
if( X->p[i - 1] != 0 ) |
break; |
for( j = Y->n; j > 0; j-- ) |
if( Y->p[j - 1] != 0 ) |
break; |
if( i == 0 && j == 0 ) |
return( 0 ); |
if( i > j ) return( X->s ); |
if( j > i ) return( -Y->s ); |
if( X->s > 0 && Y->s < 0 ) return( 1 ); |
if( Y->s > 0 && X->s < 0 ) return( -1 ); |
for( ; i > 0; i-- ) |
{ |
if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); |
if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); |
} |
return( 0 ); |
} |
/** Decide if an integer is less than the other, without branches. |
* |
* \param x First integer. |
* \param y Second integer. |
* |
* \return 1 if \p x is less than \p y, 0 otherwise |
*/ |
static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, |
const mbedtls_mpi_uint y ) |
{ |
mbedtls_mpi_uint ret; |
mbedtls_mpi_uint cond; |
/* |
* Check if the most significant bits (MSB) of the operands are different. |
*/ |
cond = ( x ^ y ); |
/* |
* If the MSB are the same then the difference x-y will be negative (and |
* have its MSB set to 1 during conversion to unsigned) if and only if x<y. |
*/ |
ret = ( x - y ) & ~cond; |
/* |
* If the MSB are different, then the operand with the MSB of 1 is the |
* bigger. (That is if y has MSB of 1, then x<y is true and it is false if |
* the MSB of y is 0.) |
*/ |
ret |= y & cond; |
ret = ret >> ( biL - 1 ); |
return (unsigned) ret; |
} |
/* |
* Compare signed values in constant time |
*/ |
int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, |
unsigned *ret ) |
{ |
size_t i; |
/* The value of any of these variables is either 0 or 1 at all times. */ |
unsigned cond, done, X_is_negative, Y_is_negative; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( Y != NULL ); |
MPI_VALIDATE_RET( ret != NULL ); |
if( X->n != Y->n ) |
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; |
/* |
* Set sign_N to 1 if N >= 0, 0 if N < 0. |
* We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. |
*/ |
X_is_negative = ( X->s & 2 ) >> 1; |
Y_is_negative = ( Y->s & 2 ) >> 1; |
/* |
* If the signs are different, then the positive operand is the bigger. |
* That is if X is negative (X_is_negative == 1), then X < Y is true and it |
* is false if X is positive (X_is_negative == 0). |
*/ |
cond = ( X_is_negative ^ Y_is_negative ); |
*ret = cond & X_is_negative; |
/* |
* This is a constant-time function. We might have the result, but we still |
* need to go through the loop. Record if we have the result already. |
*/ |
done = cond; |
for( i = X->n; i > 0; i-- ) |
{ |
/* |
* If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both |
* X and Y are negative. |
* |
* Again even if we can make a decision, we just mark the result and |
* the fact that we are done and continue looping. |
*/ |
cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); |
*ret |= cond & ( 1 - done ) & X_is_negative; |
done |= cond; |
/* |
* If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both |
* X and Y are positive. |
* |
* Again even if we can make a decision, we just mark the result and |
* the fact that we are done and continue looping. |
*/ |
cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); |
*ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); |
done |= cond; |
} |
return( 0 ); |
} |
/* |
* Compare signed values |
*/ |
int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) |
{ |
mbedtls_mpi Y; |
mbedtls_mpi_uint p[1]; |
MPI_VALIDATE_RET( X != NULL ); |
*p = ( z < 0 ) ? -z : z; |
Y.s = ( z < 0 ) ? -1 : 1; |
Y.n = 1; |
Y.p = p; |
return( mbedtls_mpi_cmp_mpi( X, &Y ) ); |
} |
/* |
* Unsigned addition: X = |A| + |B| (HAC 14.7) |
*/ |
int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) |
{ |
int ret; |
size_t i, j; |
mbedtls_mpi_uint *o, *p, c, tmp; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
if( X == B ) |
{ |
const mbedtls_mpi *T = A; A = X; B = T; |
} |
if( X != A ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); |
/* |
* X should always be positive as a result of unsigned additions. |
*/ |
X->s = 1; |
for( j = B->n; j > 0; j-- ) |
if( B->p[j - 1] != 0 ) |
break; |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); |
o = B->p; p = X->p; c = 0; |
/* |
* tmp is used because it might happen that p == o |
*/ |
for( i = 0; i < j; i++, o++, p++ ) |
{ |
tmp= *o; |
*p += c; c = ( *p < c ); |
*p += tmp; c += ( *p < tmp ); |
} |
while( c != 0 ) |
{ |
if( i >= X->n ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); |
p = X->p + i; |
} |
*p += c; c = ( *p < c ); i++; p++; |
} |
cleanup: |
return( ret ); |
} |
/* |
* Helper for mbedtls_mpi subtraction |
*/ |
static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) |
{ |
size_t i; |
mbedtls_mpi_uint c, z; |
for( i = c = 0; i < n; i++, s++, d++ ) |
{ |
z = ( *d < c ); *d -= c; |
c = ( *d < *s ) + z; *d -= *s; |
} |
while( c != 0 ) |
{ |
z = ( *d < c ); *d -= c; |
c = z; d++; |
} |
} |
/* |
* Unsigned subtraction: X = |A| - |B| (HAC 14.9) |
*/ |
int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) |
{ |
mbedtls_mpi TB; |
int ret; |
size_t n; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) |
return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); |
mbedtls_mpi_init( &TB ); |
if( X == B ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); |
B = &TB; |
} |
if( X != A ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); |
/* |
* X should always be positive as a result of unsigned subtractions. |
*/ |
X->s = 1; |
ret = 0; |
for( n = B->n; n > 0; n-- ) |
if( B->p[n - 1] != 0 ) |
break; |
mpi_sub_hlp( n, B->p, X->p ); |
cleanup: |
mbedtls_mpi_free( &TB ); |
return( ret ); |
} |
/* |
* Signed addition: X = A + B |
*/ |
int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) |
{ |
int ret, s; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
s = A->s; |
if( A->s * B->s < 0 ) |
{ |
if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); |
X->s = s; |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); |
X->s = -s; |
} |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); |
X->s = s; |
} |
cleanup: |
return( ret ); |
} |
/* |
* Signed subtraction: X = A - B |
*/ |
int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) |
{ |
int ret, s; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
s = A->s; |
if( A->s * B->s > 0 ) |
{ |
if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); |
X->s = s; |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); |
X->s = -s; |
} |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); |
X->s = s; |
} |
cleanup: |
return( ret ); |
} |
/* |
* Signed addition: X = A + b |
*/ |
int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) |
{ |
mbedtls_mpi _B; |
mbedtls_mpi_uint p[1]; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
p[0] = ( b < 0 ) ? -b : b; |
_B.s = ( b < 0 ) ? -1 : 1; |
_B.n = 1; |
_B.p = p; |
return( mbedtls_mpi_add_mpi( X, A, &_B ) ); |
} |
/* |
* Signed subtraction: X = A - b |
*/ |
int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) |
{ |
mbedtls_mpi _B; |
mbedtls_mpi_uint p[1]; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
p[0] = ( b < 0 ) ? -b : b; |
_B.s = ( b < 0 ) ? -1 : 1; |
_B.n = 1; |
_B.p = p; |
return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); |
} |
/* |
* Helper for mbedtls_mpi multiplication |
*/ |
static |
#if defined(__APPLE__) && defined(__arm__) |
/* |
* Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) |
* appears to need this to prevent bad ARM code generation at -O3. |
*/ |
__attribute__ ((noinline)) |
#endif |
void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) |
{ |
mbedtls_mpi_uint c = 0, t = 0; |
#if defined(MULADDC_HUIT) |
for( ; i >= 8; i -= 8 ) |
{ |
MULADDC_INIT |
MULADDC_HUIT |
MULADDC_STOP |
} |
for( ; i > 0; i-- ) |
{ |
MULADDC_INIT |
MULADDC_CORE |
MULADDC_STOP |
} |
#else /* MULADDC_HUIT */ |
for( ; i >= 16; i -= 16 ) |
{ |
MULADDC_INIT |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_STOP |
} |
for( ; i >= 8; i -= 8 ) |
{ |
MULADDC_INIT |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_CORE MULADDC_CORE |
MULADDC_STOP |
} |
for( ; i > 0; i-- ) |
{ |
MULADDC_INIT |
MULADDC_CORE |
MULADDC_STOP |
} |
#endif /* MULADDC_HUIT */ |
t++; |
do { |
*d += c; c = ( *d < c ); d++; |
} |
while( c != 0 ); |
} |
/* |
* Baseline multiplication: X = A * B (HAC 14.12) |
*/ |
int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) |
{ |
int ret; |
size_t i, j; |
mbedtls_mpi TA, TB; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); |
if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } |
if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } |
for( i = A->n; i > 0; i-- ) |
if( A->p[i - 1] != 0 ) |
break; |
for( j = B->n; j > 0; j-- ) |
if( B->p[j - 1] != 0 ) |
break; |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); |
for( ; j > 0; j-- ) |
mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); |
X->s = A->s * B->s; |
cleanup: |
mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); |
return( ret ); |
} |
/* |
* Baseline multiplication: X = A * b |
*/ |
int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) |
{ |
mbedtls_mpi _B; |
mbedtls_mpi_uint p[1]; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
_B.s = 1; |
_B.n = 1; |
_B.p = p; |
p[0] = b; |
return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); |
} |
/* |
* Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and |
* mbedtls_mpi_uint divisor, d |
*/ |
static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, |
mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) |
{ |
#if defined(MBEDTLS_HAVE_UDBL) |
mbedtls_t_udbl dividend, quotient; |
#else |
const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; |
const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; |
mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; |
mbedtls_mpi_uint u0_msw, u0_lsw; |
size_t s; |
#endif |
/* |
* Check for overflow |
*/ |
if( 0 == d || u1 >= d ) |
{ |
if (r != NULL) *r = ~0; |
return ( ~0 ); |
} |
#if defined(MBEDTLS_HAVE_UDBL) |
dividend = (mbedtls_t_udbl) u1 << biL; |
dividend |= (mbedtls_t_udbl) u0; |
quotient = dividend / d; |
if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) |
quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; |
if( r != NULL ) |
*r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); |
return (mbedtls_mpi_uint) quotient; |
#else |
/* |
* Algorithm D, Section 4.3.1 - The Art of Computer Programming |
* Vol. 2 - Seminumerical Algorithms, Knuth |
*/ |
/* |
* Normalize the divisor, d, and dividend, u0, u1 |
*/ |
s = mbedtls_clz( d ); |
d = d << s; |
u1 = u1 << s; |
u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); |
u0 = u0 << s; |
d1 = d >> biH; |
d0 = d & uint_halfword_mask; |
u0_msw = u0 >> biH; |
u0_lsw = u0 & uint_halfword_mask; |
/* |
* Find the first quotient and remainder |
*/ |
q1 = u1 / d1; |
r0 = u1 - d1 * q1; |
while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) |
{ |
q1 -= 1; |
r0 += d1; |
if ( r0 >= radix ) break; |
} |
rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); |
q0 = rAX / d1; |
r0 = rAX - q0 * d1; |
while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) |
{ |
q0 -= 1; |
r0 += d1; |
if ( r0 >= radix ) break; |
} |
if (r != NULL) |
*r = ( rAX * radix + u0_lsw - q0 * d ) >> s; |
quotient = q1 * radix + q0; |
return quotient; |
#endif |
} |
/* |
* Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) |
*/ |
int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, |
const mbedtls_mpi *B ) |
{ |
int ret; |
size_t i, n, t, k; |
mbedtls_mpi X, Y, Z, T1, T2; |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) |
return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); |
mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); |
mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); |
if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) |
{ |
if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); |
if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); |
return( 0 ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); |
X.s = Y.s = 1; |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); |
k = mbedtls_mpi_bitlen( &Y ) % biL; |
if( k < biL - 1 ) |
{ |
k = biL - 1 - k; |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); |
} |
else k = 0; |
n = X.n - 1; |
t = Y.n - 1; |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); |
while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) |
{ |
Z.p[n - t]++; |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); |
for( i = n; i > t ; i-- ) |
{ |
if( X.p[i] >= Y.p[t] ) |
Z.p[i - t - 1] = ~0; |
else |
{ |
Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], |
Y.p[t], NULL); |
} |
Z.p[i - t - 1]++; |
do |
{ |
Z.p[i - t - 1]--; |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); |
T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; |
T1.p[1] = Y.p[t]; |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); |
T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; |
T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; |
T2.p[2] = X.p[i]; |
} |
while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); |
if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); |
Z.p[i - t - 1]--; |
} |
} |
if( Q != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); |
Q->s = A->s * B->s; |
} |
if( R != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); |
X.s = A->s; |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); |
if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) |
R->s = 1; |
} |
cleanup: |
mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); |
mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); |
return( ret ); |
} |
/* |
* Division by int: A = Q * b + R |
*/ |
int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, |
const mbedtls_mpi *A, |
mbedtls_mpi_sint b ) |
{ |
mbedtls_mpi _B; |
mbedtls_mpi_uint p[1]; |
MPI_VALIDATE_RET( A != NULL ); |
p[0] = ( b < 0 ) ? -b : b; |
_B.s = ( b < 0 ) ? -1 : 1; |
_B.n = 1; |
_B.p = p; |
return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); |
} |
/* |
* Modulo: R = A mod B |
*/ |
int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) |
{ |
int ret; |
MPI_VALIDATE_RET( R != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) |
return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); |
while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); |
while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Modulo: r = A mod b |
*/ |
int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) |
{ |
size_t i; |
mbedtls_mpi_uint x, y, z; |
MPI_VALIDATE_RET( r != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
if( b == 0 ) |
return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); |
if( b < 0 ) |
return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); |
/* |
* handle trivial cases |
*/ |
if( b == 1 ) |
{ |
*r = 0; |
return( 0 ); |
} |
if( b == 2 ) |
{ |
*r = A->p[0] & 1; |
return( 0 ); |
} |
/* |
* general case |
*/ |
for( i = A->n, y = 0; i > 0; i-- ) |
{ |
x = A->p[i - 1]; |
y = ( y << biH ) | ( x >> biH ); |
z = y / b; |
y -= z * b; |
x <<= biH; |
y = ( y << biH ) | ( x >> biH ); |
z = y / b; |
y -= z * b; |
} |
/* |
* If A is negative, then the current y represents a negative value. |
* Flipping it to the positive side. |
*/ |
if( A->s < 0 && y != 0 ) |
y = b - y; |
*r = y; |
return( 0 ); |
} |
/* |
* Fast Montgomery initialization (thanks to Tom St Denis) |
*/ |
static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) |
{ |
mbedtls_mpi_uint x, m0 = N->p[0]; |
unsigned int i; |
x = m0; |
x += ( ( m0 + 2 ) & 4 ) << 1; |
for( i = biL; i >= 8; i /= 2 ) |
x *= ( 2 - ( m0 * x ) ); |
*mm = ~x + 1; |
} |
/* |
* Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) |
*/ |
static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, |
const mbedtls_mpi *T ) |
{ |
size_t i, n, m; |
mbedtls_mpi_uint u0, u1, *d; |
if( T->n < N->n + 1 || T->p == NULL ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
memset( T->p, 0, T->n * ciL ); |
d = T->p; |
n = N->n; |
m = ( B->n < n ) ? B->n : n; |
for( i = 0; i < n; i++ ) |
{ |
/* |
* T = (T + u0*B + u1*N) / 2^biL |
*/ |
u0 = A->p[i]; |
u1 = ( d[0] + u0 * B->p[0] ) * mm; |
mpi_mul_hlp( m, B->p, d, u0 ); |
mpi_mul_hlp( n, N->p, d, u1 ); |
*d++ = u0; d[n + 1] = 0; |
} |
memcpy( A->p, d, ( n + 1 ) * ciL ); |
if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) |
mpi_sub_hlp( n, N->p, A->p ); |
else |
/* prevent timing attacks */ |
mpi_sub_hlp( n, A->p, T->p ); |
return( 0 ); |
} |
/* |
* Montgomery reduction: A = A * R^-1 mod N |
*/ |
static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, |
mbedtls_mpi_uint mm, const mbedtls_mpi *T ) |
{ |
mbedtls_mpi_uint z = 1; |
mbedtls_mpi U; |
U.n = U.s = (int) z; |
U.p = &z; |
return( mpi_montmul( A, &U, N, mm, T ) ); |
} |
/* |
* Sliding-window exponentiation: X = A^E mod N (HAC 14.85) |
*/ |
int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, |
const mbedtls_mpi *E, const mbedtls_mpi *N, |
mbedtls_mpi *_RR ) |
{ |
int ret; |
size_t wbits, wsize, one = 1; |
size_t i, j, nblimbs; |
size_t bufsize, nbits; |
mbedtls_mpi_uint ei, mm, state; |
mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; |
int neg; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( E != NULL ); |
MPI_VALIDATE_RET( N != NULL ); |
if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
/* |
* Init temps and window size |
*/ |
mpi_montg_init( &mm, N ); |
mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); |
mbedtls_mpi_init( &Apos ); |
memset( W, 0, sizeof( W ) ); |
i = mbedtls_mpi_bitlen( E ); |
wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : |
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; |
#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) |
if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) |
wsize = MBEDTLS_MPI_WINDOW_SIZE; |
#endif |
j = N->n + 1; |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); |
/* |
* Compensate for negative A (and correct at the end) |
*/ |
neg = ( A->s == -1 ); |
if( neg ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); |
Apos.s = 1; |
A = &Apos; |
} |
/* |
* If 1st call, pre-compute R^2 mod N |
*/ |
if( _RR == NULL || _RR->p == NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); |
if( _RR != NULL ) |
memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); |
} |
else |
memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); |
/* |
* W[1] = A * R^2 * R^-1 mod N = A * R mod N |
*/ |
if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); |
else |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); |
MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); |
/* |
* X = R^2 * R^-1 mod N = R mod N |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); |
MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); |
if( wsize > 1 ) |
{ |
/* |
* W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) |
*/ |
j = one << ( wsize - 1 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); |
for( i = 0; i < wsize - 1; i++ ) |
MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); |
/* |
* W[i] = W[i - 1] * W[1] |
*/ |
for( i = j + 1; i < ( one << wsize ); i++ ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); |
MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); |
} |
} |
nblimbs = E->n; |
bufsize = 0; |
nbits = 0; |
wbits = 0; |
state = 0; |
while( 1 ) |
{ |
if( bufsize == 0 ) |
{ |
if( nblimbs == 0 ) |
break; |
nblimbs--; |
bufsize = sizeof( mbedtls_mpi_uint ) << 3; |
} |
bufsize--; |
ei = (E->p[nblimbs] >> bufsize) & 1; |
/* |
* skip leading 0s |
*/ |
if( ei == 0 && state == 0 ) |
continue; |
if( ei == 0 && state == 1 ) |
{ |
/* |
* out of window, square X |
*/ |
MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); |
continue; |
} |
/* |
* add ei to current window |
*/ |
state = 2; |
nbits++; |
wbits |= ( ei << ( wsize - nbits ) ); |
if( nbits == wsize ) |
{ |
/* |
* X = X^wsize R^-1 mod N |
*/ |
for( i = 0; i < wsize; i++ ) |
MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); |
/* |
* X = X * W[wbits] R^-1 mod N |
*/ |
MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); |
state--; |
nbits = 0; |
wbits = 0; |
} |
} |
/* |
* process the remaining bits |
*/ |
for( i = 0; i < nbits; i++ ) |
{ |
MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); |
wbits <<= 1; |
if( ( wbits & ( one << wsize ) ) != 0 ) |
MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); |
} |
/* |
* X = A^E * R * R^-1 mod N = A^E mod N |
*/ |
MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); |
if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) |
{ |
X->s = -1; |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); |
} |
cleanup: |
for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) |
mbedtls_mpi_free( &W[i] ); |
mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); |
if( _RR == NULL || _RR->p == NULL ) |
mbedtls_mpi_free( &RR ); |
return( ret ); |
} |
/* |
* Greatest common divisor: G = gcd(A, B) (HAC 14.54) |
*/ |
int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) |
{ |
int ret; |
size_t lz, lzt; |
mbedtls_mpi TG, TA, TB; |
MPI_VALIDATE_RET( G != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( B != NULL ); |
mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); |
lz = mbedtls_mpi_lsb( &TA ); |
lzt = mbedtls_mpi_lsb( &TB ); |
if( lzt < lz ) |
lz = lzt; |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); |
TA.s = TB.s = 1; |
while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); |
if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); |
} |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); |
cleanup: |
mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); |
return( ret ); |
} |
/* |
* Fill X with size bytes of random. |
* |
* Use a temporary bytes representation to make sure the result is the same |
* regardless of the platform endianness (useful when f_rng is actually |
* deterministic, eg for tests). |
*/ |
int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
size_t const limbs = CHARS_TO_LIMBS( size ); |
size_t const overhead = ( limbs * ciL ) - size; |
unsigned char *Xp; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( f_rng != NULL ); |
/* Ensure that target MPI has exactly the necessary number of limbs */ |
if( X->n != limbs ) |
{ |
mbedtls_mpi_free( X ); |
mbedtls_mpi_init( X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); |
Xp = (unsigned char*) X->p; |
f_rng( p_rng, Xp + overhead, size ); |
mpi_bigendian_to_host( X->p, limbs ); |
cleanup: |
return( ret ); |
} |
/* |
* Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) |
*/ |
int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) |
{ |
int ret; |
mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( A != NULL ); |
MPI_VALIDATE_RET( N != NULL ); |
if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); |
mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); |
mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); |
if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) |
{ |
ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); |
do |
{ |
while( ( TU.p[0] & 1 ) == 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); |
if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); |
} |
while( ( TV.p[0] & 1 ) == 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); |
if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); |
} |
if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); |
} |
} |
while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); |
while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); |
while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); |
cleanup: |
mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); |
mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); |
mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); |
return( ret ); |
} |
#if defined(MBEDTLS_GENPRIME) |
static const int small_prime[] = |
{ |
3, 5, 7, 11, 13, 17, 19, 23, |
29, 31, 37, 41, 43, 47, 53, 59, |
61, 67, 71, 73, 79, 83, 89, 97, |
101, 103, 107, 109, 113, 127, 131, 137, |
139, 149, 151, 157, 163, 167, 173, 179, |
181, 191, 193, 197, 199, 211, 223, 227, |
229, 233, 239, 241, 251, 257, 263, 269, |
271, 277, 281, 283, 293, 307, 311, 313, |
317, 331, 337, 347, 349, 353, 359, 367, |
373, 379, 383, 389, 397, 401, 409, 419, |
421, 431, 433, 439, 443, 449, 457, 461, |
463, 467, 479, 487, 491, 499, 503, 509, |
521, 523, 541, 547, 557, 563, 569, 571, |
577, 587, 593, 599, 601, 607, 613, 617, |
619, 631, 641, 643, 647, 653, 659, 661, |
673, 677, 683, 691, 701, 709, 719, 727, |
733, 739, 743, 751, 757, 761, 769, 773, |
787, 797, 809, 811, 821, 823, 827, 829, |
839, 853, 857, 859, 863, 877, 881, 883, |
887, 907, 911, 919, 929, 937, 941, 947, |
953, 967, 971, 977, 983, 991, 997, -103 |
}; |
/* |
* Small divisors test (X must be positive) |
* |
* Return values: |
* 0: no small factor (possible prime, more tests needed) |
* 1: certain prime |
* MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime |
* other negative: error |
*/ |
static int mpi_check_small_factors( const mbedtls_mpi *X ) |
{ |
int ret = 0; |
size_t i; |
mbedtls_mpi_uint r; |
if( ( X->p[0] & 1 ) == 0 ) |
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); |
for( i = 0; small_prime[i] > 0; i++ ) |
{ |
if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) |
return( 1 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); |
if( r == 0 ) |
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); |
} |
cleanup: |
return( ret ); |
} |
/* |
* Miller-Rabin pseudo-primality test (HAC 4.24) |
*/ |
static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret, count; |
size_t i, j, k, s; |
mbedtls_mpi W, R, T, A, RR; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( f_rng != NULL ); |
mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); |
mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); |
mbedtls_mpi_init( &RR ); |
/* |
* W = |X| - 1 |
* R = W >> lsb( W ) |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); |
s = mbedtls_mpi_lsb( &W ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); |
for( i = 0; i < rounds; i++ ) |
{ |
/* |
* pick a random A, 1 < A < |X| - 1 |
*/ |
count = 0; |
do { |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); |
j = mbedtls_mpi_bitlen( &A ); |
k = mbedtls_mpi_bitlen( &W ); |
if (j > k) { |
A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; |
} |
if (count++ > 30) { |
ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; |
goto cleanup; |
} |
} while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || |
mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); |
/* |
* A = A^R mod |X| |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); |
if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || |
mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) |
continue; |
j = 1; |
while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) |
{ |
/* |
* A = A * A mod |X| |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); |
if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) |
break; |
j++; |
} |
/* |
* not prime if A != |X| - 1 or A == 1 |
*/ |
if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || |
mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) |
{ |
ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; |
break; |
} |
} |
cleanup: |
mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); |
mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); |
mbedtls_mpi_free( &RR ); |
return( ret ); |
} |
/* |
* Pseudo-primality test: small factors, then Miller-Rabin |
*/ |
int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
mbedtls_mpi XX; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( f_rng != NULL ); |
XX.s = 1; |
XX.n = X->n; |
XX.p = X->p; |
if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || |
mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) |
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); |
if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) |
return( 0 ); |
if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) |
{ |
if( ret == 1 ) |
return( 0 ); |
return( ret ); |
} |
return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
/* |
* Pseudo-primality test, error probability 2^-80 |
*/ |
int mbedtls_mpi_is_prime( const mbedtls_mpi *X, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( f_rng != NULL ); |
/* |
* In the past our key generation aimed for an error rate of at most |
* 2^-80. Since this function is deprecated, aim for the same certainty |
* here as well. |
*/ |
return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); |
} |
#endif |
/* |
* Prime number generation |
* |
* To generate an RSA key in a way recommended by FIPS 186-4, both primes must |
* be either 1024 bits or 1536 bits long, and flags must contain |
* MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. |
*/ |
int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
#ifdef MBEDTLS_HAVE_INT64 |
// ceil(2^63.5) |
#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL |
#else |
// ceil(2^31.5) |
#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U |
#endif |
int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; |
size_t k, n; |
int rounds; |
mbedtls_mpi_uint r; |
mbedtls_mpi Y; |
MPI_VALIDATE_RET( X != NULL ); |
MPI_VALIDATE_RET( f_rng != NULL ); |
if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
mbedtls_mpi_init( &Y ); |
n = BITS_TO_LIMBS( nbits ); |
if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) |
{ |
/* |
* 2^-80 error probability, number of rounds chosen per HAC, table 4.4 |
*/ |
rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : |
( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : |
( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); |
} |
else |
{ |
/* |
* 2^-100 error probability, number of rounds computed based on HAC, |
* fact 4.48 |
*/ |
rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : |
( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : |
( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : |
( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); |
} |
while( 1 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); |
/* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ |
if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; |
k = n * biL; |
if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); |
X->p[0] |= 1; |
if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) |
{ |
ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); |
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) |
goto cleanup; |
} |
else |
{ |
/* |
* An necessary condition for Y and X = 2Y + 1 to be prime |
* is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). |
* Make sure it is satisfied, while keeping X = 3 mod 4 |
*/ |
X->p[0] |= 2; |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); |
if( r == 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); |
else if( r == 1 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); |
/* Set Y = (X-1) / 2, which is X / 2 because X is odd */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); |
while( 1 ) |
{ |
/* |
* First, check small factors for X and Y |
* before doing Miller-Rabin on any of them |
*/ |
if( ( ret = mpi_check_small_factors( X ) ) == 0 && |
( ret = mpi_check_small_factors( &Y ) ) == 0 && |
( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) |
== 0 && |
( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) |
== 0 ) |
goto cleanup; |
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) |
goto cleanup; |
/* |
* Next candidates. We want to preserve Y = (X-1) / 2 and |
* Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) |
* so up Y by 6 and X by 12. |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); |
} |
} |
} |
cleanup: |
mbedtls_mpi_free( &Y ); |
return( ret ); |
} |
#endif /* MBEDTLS_GENPRIME */ |
#if defined(MBEDTLS_SELF_TEST) |
#define GCD_PAIR_COUNT 3 |
static const int gcd_pairs[GCD_PAIR_COUNT][3] = |
{ |
{ 693, 609, 21 }, |
{ 1764, 868, 28 }, |
{ 768454923, 542167814, 1 } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_mpi_self_test( int verbose ) |
{ |
int ret, i; |
mbedtls_mpi A, E, N, X, Y, U, V; |
mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); |
mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, |
"EFE021C2645FD1DC586E69184AF4A31E" \ |
"D5F53E93B5F123FA41680867BA110131" \ |
"944FE7952E2517337780CB0DB80E61AA" \ |
"E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, |
"B2E7EFD37075B9F03FF989C7C5051C20" \ |
"34D2A323810251127E7BF8625A4F49A5" \ |
"F3E27F4DA8BD59C47D6DAABA4C8127BD" \ |
"5B5C25763222FEFCCFC38B832366C29E" ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, |
"0066A198186C18C10B2F5ED9B522752A" \ |
"9830B69916E535C8F047518A889A43A5" \ |
"94B6BED27A168D31D4A52F88925AA8F5" ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, |
"602AB7ECA597A3D6B56FF9829A5E8B85" \ |
"9E857EA95A03512E2BAE7391688D264A" \ |
"A5663B0341DB9CCFD2C4C5F421FEC814" \ |
"8001B72E848A38CAE1C65F78E56ABDEF" \ |
"E12D3C039B8A02D6BE593F0BBBDA56F1" \ |
"ECF677152EF804370C1A305CAF3B5BF1" \ |
"30879B56C61DE584A0F53A2447A51E" ) ); |
if( verbose != 0 ) |
mbedtls_printf( " MPI test #1 (mul_mpi): " ); |
if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, |
"256567336059E52CAE22925474705F39A94" ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, |
"6613F26162223DF488E9CD48CC132C7A" \ |
"0AC93C701B001B092E4E5B9F73BCD27B" \ |
"9EE50D0657C77F374E903CDFA4C642" ) ); |
if( verbose != 0 ) |
mbedtls_printf( " MPI test #2 (div_mpi): " ); |
if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || |
mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, |
"36E139AEA55215609D2816998ED020BB" \ |
"BD96C37890F65171D948E9BC7CBAA4D9" \ |
"325D24D6A3C12710F10A09FA08AB87" ) ); |
if( verbose != 0 ) |
mbedtls_printf( " MPI test #3 (exp_mod): " ); |
if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, |
"003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ |
"C3DBA76456363A10869622EAC2DD84EC" \ |
"C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); |
if( verbose != 0 ) |
mbedtls_printf( " MPI test #4 (inv_mod): " ); |
if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " MPI test #5 (simple gcd): " ); |
for( i = 0; i < GCD_PAIR_COUNT; i++ ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); |
if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed at %d\n", i ); |
ret = 1; |
goto cleanup; |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
cleanup: |
if( ret != 0 && verbose != 0 ) |
mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); |
mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); |
mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_BIGNUM_C */ |
/programs/develop/libraries/kos_mbedtls/library/blowfish.c |
---|
0,0 → 1,698 |
/* |
* Blowfish implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The Blowfish block cipher was designed by Bruce Schneier in 1993. |
* http://www.schneier.com/blowfish.html |
* http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 |
* |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_BLOWFISH_C) |
#include "mbedtls/blowfish.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if !defined(MBEDTLS_BLOWFISH_ALT) |
/* Parameter validation macros */ |
#define BLOWFISH_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ) |
#define BLOWFISH_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* 32-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} |
#endif |
static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { |
0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, |
0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, |
0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, |
0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, |
0x9216D5D9L, 0x8979FB1BL |
}; |
/* declarations of data at the end of this file */ |
static const uint32_t S[4][256]; |
static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) |
{ |
unsigned short a, b, c, d; |
uint32_t y; |
d = (unsigned short)(x & 0xFF); |
x >>= 8; |
c = (unsigned short)(x & 0xFF); |
x >>= 8; |
b = (unsigned short)(x & 0xFF); |
x >>= 8; |
a = (unsigned short)(x & 0xFF); |
y = ctx->S[0][a] + ctx->S[1][b]; |
y = y ^ ctx->S[2][c]; |
y = y + ctx->S[3][d]; |
return( y ); |
} |
static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) |
{ |
uint32_t Xl, Xr, temp; |
short i; |
Xl = *xl; |
Xr = *xr; |
for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) |
{ |
Xl = Xl ^ ctx->P[i]; |
Xr = F( ctx, Xl ) ^ Xr; |
temp = Xl; |
Xl = Xr; |
Xr = temp; |
} |
temp = Xl; |
Xl = Xr; |
Xr = temp; |
Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; |
Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; |
*xl = Xl; |
*xr = Xr; |
} |
static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) |
{ |
uint32_t Xl, Xr, temp; |
short i; |
Xl = *xl; |
Xr = *xr; |
for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) |
{ |
Xl = Xl ^ ctx->P[i]; |
Xr = F( ctx, Xl ) ^ Xr; |
temp = Xl; |
Xl = Xr; |
Xr = temp; |
} |
temp = Xl; |
Xl = Xr; |
Xr = temp; |
Xr = Xr ^ ctx->P[1]; |
Xl = Xl ^ ctx->P[0]; |
*xl = Xl; |
*xr = Xr; |
} |
void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) |
{ |
BLOWFISH_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); |
} |
void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); |
} |
/* |
* Blowfish key schedule |
*/ |
int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, |
const unsigned char *key, |
unsigned int keybits ) |
{ |
unsigned int i, j, k; |
uint32_t data, datal, datar; |
BLOWFISH_VALIDATE_RET( ctx != NULL ); |
BLOWFISH_VALIDATE_RET( key != NULL ); |
if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || |
keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || |
keybits % 8 != 0 ) |
{ |
return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); |
} |
keybits >>= 3; |
for( i = 0; i < 4; i++ ) |
{ |
for( j = 0; j < 256; j++ ) |
ctx->S[i][j] = S[i][j]; |
} |
j = 0; |
for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) |
{ |
data = 0x00000000; |
for( k = 0; k < 4; ++k ) |
{ |
data = ( data << 8 ) | key[j++]; |
if( j >= keybits ) |
j = 0; |
} |
ctx->P[i] = P[i] ^ data; |
} |
datal = 0x00000000; |
datar = 0x00000000; |
for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) |
{ |
blowfish_enc( ctx, &datal, &datar ); |
ctx->P[i] = datal; |
ctx->P[i + 1] = datar; |
} |
for( i = 0; i < 4; i++ ) |
{ |
for( j = 0; j < 256; j += 2 ) |
{ |
blowfish_enc( ctx, &datal, &datar ); |
ctx->S[i][j] = datal; |
ctx->S[i][j + 1] = datar; |
} |
} |
return( 0 ); |
} |
/* |
* Blowfish-ECB block encryption/decryption |
*/ |
int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, |
int mode, |
const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], |
unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) |
{ |
uint32_t X0, X1; |
BLOWFISH_VALIDATE_RET( ctx != NULL ); |
BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || |
mode == MBEDTLS_BLOWFISH_DECRYPT ); |
BLOWFISH_VALIDATE_RET( input != NULL ); |
BLOWFISH_VALIDATE_RET( output != NULL ); |
GET_UINT32_BE( X0, input, 0 ); |
GET_UINT32_BE( X1, input, 4 ); |
if( mode == MBEDTLS_BLOWFISH_DECRYPT ) |
{ |
blowfish_dec( ctx, &X0, &X1 ); |
} |
else /* MBEDTLS_BLOWFISH_ENCRYPT */ |
{ |
blowfish_enc( ctx, &X0, &X1 ); |
} |
PUT_UINT32_BE( X0, output, 0 ); |
PUT_UINT32_BE( X1, output, 4 ); |
return( 0 ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* Blowfish-CBC buffer encryption/decryption |
*/ |
int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int i; |
unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; |
BLOWFISH_VALIDATE_RET( ctx != NULL ); |
BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || |
mode == MBEDTLS_BLOWFISH_DECRYPT ); |
BLOWFISH_VALIDATE_RET( iv != NULL ); |
BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); |
BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); |
if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) |
return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); |
if( mode == MBEDTLS_BLOWFISH_DECRYPT ) |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); |
mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); |
for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); |
input += MBEDTLS_BLOWFISH_BLOCKSIZE; |
output += MBEDTLS_BLOWFISH_BLOCKSIZE; |
length -= MBEDTLS_BLOWFISH_BLOCKSIZE; |
} |
} |
else |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); |
memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); |
input += MBEDTLS_BLOWFISH_BLOCKSIZE; |
output += MBEDTLS_BLOWFISH_BLOCKSIZE; |
length -= MBEDTLS_BLOWFISH_BLOCKSIZE; |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
/* |
* Blowfish CFB buffer encryption/decryption |
*/ |
int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, |
int mode, |
size_t length, |
size_t *iv_off, |
unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c; |
size_t n; |
BLOWFISH_VALIDATE_RET( ctx != NULL ); |
BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || |
mode == MBEDTLS_BLOWFISH_DECRYPT ); |
BLOWFISH_VALIDATE_RET( iv != NULL ); |
BLOWFISH_VALIDATE_RET( iv_off != NULL ); |
BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); |
BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); |
n = *iv_off; |
if( n >= 8 ) |
return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); |
if( mode == MBEDTLS_BLOWFISH_DECRYPT ) |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); |
c = *input++; |
*output++ = (unsigned char)( c ^ iv[n] ); |
iv[n] = (unsigned char) c; |
n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; |
} |
} |
else |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); |
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); |
n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; |
} |
} |
*iv_off = n; |
return( 0 ); |
} |
#endif /*MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* Blowfish CTR buffer encryption/decryption |
*/ |
int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, |
size_t length, |
size_t *nc_off, |
unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], |
unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c, i; |
size_t n; |
BLOWFISH_VALIDATE_RET( ctx != NULL ); |
BLOWFISH_VALIDATE_RET( nonce_counter != NULL ); |
BLOWFISH_VALIDATE_RET( stream_block != NULL ); |
BLOWFISH_VALIDATE_RET( nc_off != NULL ); |
BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); |
BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); |
n = *nc_off; |
if( n >= 8 ) |
return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); |
while( length-- ) |
{ |
if( n == 0 ) { |
mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, |
stream_block ); |
for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) |
if( ++nonce_counter[i - 1] != 0 ) |
break; |
} |
c = *input++; |
*output++ = (unsigned char)( c ^ stream_block[n] ); |
n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; |
} |
*nc_off = n; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
static const uint32_t S[4][256] = { |
{ 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, |
0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, |
0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, |
0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, |
0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, |
0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, |
0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, |
0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, |
0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, |
0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, |
0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, |
0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, |
0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, |
0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, |
0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, |
0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, |
0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, |
0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, |
0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, |
0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, |
0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, |
0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, |
0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, |
0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, |
0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, |
0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, |
0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, |
0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, |
0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, |
0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, |
0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, |
0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, |
0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, |
0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, |
0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, |
0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, |
0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, |
0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, |
0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, |
0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, |
0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, |
0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, |
0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, |
0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, |
0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, |
0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, |
0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, |
0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, |
0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, |
0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, |
0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, |
0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, |
0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, |
0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, |
0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, |
0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, |
0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, |
0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, |
0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, |
0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, |
0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, |
0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, |
0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, |
0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, |
{ 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, |
0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, |
0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, |
0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, |
0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, |
0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, |
0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, |
0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, |
0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, |
0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, |
0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, |
0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, |
0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, |
0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, |
0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, |
0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, |
0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, |
0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, |
0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, |
0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, |
0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, |
0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, |
0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, |
0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, |
0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, |
0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, |
0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, |
0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, |
0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, |
0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, |
0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, |
0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, |
0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, |
0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, |
0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, |
0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, |
0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, |
0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, |
0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, |
0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, |
0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, |
0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, |
0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, |
0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, |
0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, |
0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, |
0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, |
0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, |
0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, |
0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, |
0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, |
0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, |
0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, |
0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, |
0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, |
0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, |
0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, |
0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, |
0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, |
0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, |
0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, |
0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, |
0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, |
0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, |
{ 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, |
0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, |
0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, |
0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, |
0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, |
0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, |
0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, |
0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, |
0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, |
0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, |
0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, |
0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, |
0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, |
0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, |
0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, |
0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, |
0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, |
0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, |
0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, |
0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, |
0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, |
0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, |
0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, |
0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, |
0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, |
0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, |
0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, |
0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, |
0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, |
0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, |
0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, |
0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, |
0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, |
0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, |
0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, |
0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, |
0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, |
0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, |
0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, |
0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, |
0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, |
0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, |
0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, |
0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, |
0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, |
0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, |
0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, |
0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, |
0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, |
0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, |
0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, |
0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, |
0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, |
0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, |
0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, |
0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, |
0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, |
0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, |
0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, |
0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, |
0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, |
0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, |
0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, |
0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, |
{ 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, |
0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, |
0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, |
0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, |
0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, |
0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, |
0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, |
0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, |
0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, |
0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, |
0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, |
0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, |
0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, |
0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, |
0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, |
0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, |
0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, |
0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, |
0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, |
0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, |
0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, |
0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, |
0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, |
0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, |
0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, |
0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, |
0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, |
0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, |
0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, |
0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, |
0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, |
0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, |
0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, |
0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, |
0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, |
0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, |
0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, |
0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, |
0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, |
0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, |
0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, |
0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, |
0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, |
0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, |
0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, |
0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, |
0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, |
0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, |
0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, |
0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, |
0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, |
0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, |
0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, |
0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, |
0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, |
0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, |
0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, |
0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, |
0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, |
0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, |
0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, |
0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, |
0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, |
0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } |
}; |
#endif /* !MBEDTLS_BLOWFISH_ALT */ |
#endif /* MBEDTLS_BLOWFISH_C */ |
/programs/develop/libraries/kos_mbedtls/library/camellia.c |
---|
0,0 → 1,1116 |
/* |
* Camellia implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The Camellia block cipher was designed by NTT and Mitsubishi Electric |
* Corporation. |
* |
* http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CAMELLIA_C) |
#include "mbedtls/camellia.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_CAMELLIA_ALT) |
/* Parameter validation macros */ |
#define CAMELLIA_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ) |
#define CAMELLIA_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* 32-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} |
#endif |
static const unsigned char SIGMA_CHARS[6][8] = |
{ |
{ 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, |
{ 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, |
{ 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, |
{ 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, |
{ 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, |
{ 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } |
}; |
#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) |
static const unsigned char FSb[256] = |
{ |
112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, |
35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, |
134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, |
166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, |
139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, |
223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, |
20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, |
254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, |
170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, |
16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, |
135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, |
82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, |
233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, |
120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, |
114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, |
64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 |
}; |
#define SBOX1(n) FSb[(n)] |
#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) |
#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) |
#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] |
#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ |
static const unsigned char FSb[256] = |
{ |
112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, |
35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, |
134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, |
166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, |
139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, |
223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, |
20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, |
254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, |
170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, |
16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, |
135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, |
82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, |
233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, |
120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, |
114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, |
64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 |
}; |
static const unsigned char FSb2[256] = |
{ |
224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, |
70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, |
13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, |
77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, |
23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, |
191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, |
40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, |
253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, |
85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, |
32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, |
15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, |
164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, |
211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, |
240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, |
228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, |
128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 |
}; |
static const unsigned char FSb3[256] = |
{ |
56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, |
145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, |
67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, |
83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, |
197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, |
239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, |
10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, |
127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, |
85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, |
8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, |
195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, |
41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, |
244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, |
60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, |
57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, |
32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 |
}; |
static const unsigned char FSb4[256] = |
{ |
112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, |
134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, |
139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, |
20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, |
170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, |
135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, |
233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, |
114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, |
130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, |
184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, |
13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, |
88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, |
208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, |
92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, |
121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, |
7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 |
}; |
#define SBOX1(n) FSb[(n)] |
#define SBOX2(n) FSb2[(n)] |
#define SBOX3(n) FSb3[(n)] |
#define SBOX4(n) FSb4[(n)] |
#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ |
static const unsigned char shifts[2][4][4] = |
{ |
{ |
{ 1, 1, 1, 1 }, /* KL */ |
{ 0, 0, 0, 0 }, /* KR */ |
{ 1, 1, 1, 1 }, /* KA */ |
{ 0, 0, 0, 0 } /* KB */ |
}, |
{ |
{ 1, 0, 1, 1 }, /* KL */ |
{ 1, 1, 0, 1 }, /* KR */ |
{ 1, 1, 1, 0 }, /* KA */ |
{ 1, 1, 0, 1 } /* KB */ |
} |
}; |
static const signed char indexes[2][4][20] = |
{ |
{ |
{ 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, |
36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ |
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ |
{ 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, |
18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ |
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ |
}, |
{ |
{ 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, |
-1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ |
{ -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, |
18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ |
{ -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, |
56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ |
{ 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, |
22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ |
} |
}; |
static const signed char transposes[2][20] = |
{ |
{ |
21, 22, 23, 20, |
-1, -1, -1, -1, |
18, 19, 16, 17, |
11, 8, 9, 10, |
15, 12, 13, 14 |
}, |
{ |
25, 26, 27, 24, |
29, 30, 31, 28, |
18, 19, 16, 17, |
-1, -1, -1, -1, |
-1, -1, -1, -1 |
} |
}; |
/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ |
#define ROTL(DEST, SRC, SHIFT) \ |
{ \ |
(DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ |
(DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ |
(DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ |
(DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ |
} |
#define FL(XL, XR, KL, KR) \ |
{ \ |
(XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ |
(XL) = ((XR) | (KR)) ^ (XL); \ |
} |
#define FLInv(YL, YR, KL, KR) \ |
{ \ |
(YL) = ((YR) | (KR)) ^ (YL); \ |
(YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ |
} |
#define SHIFT_AND_PLACE(INDEX, OFFSET) \ |
{ \ |
TK[0] = KC[(OFFSET) * 4 + 0]; \ |
TK[1] = KC[(OFFSET) * 4 + 1]; \ |
TK[2] = KC[(OFFSET) * 4 + 2]; \ |
TK[3] = KC[(OFFSET) * 4 + 3]; \ |
\ |
for( i = 1; i <= 4; i++ ) \ |
if( shifts[(INDEX)][(OFFSET)][i -1] ) \ |
ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ |
\ |
for( i = 0; i < 20; i++ ) \ |
if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ |
RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ |
} \ |
} |
static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], |
uint32_t z[2]) |
{ |
uint32_t I0, I1; |
I0 = x[0] ^ k[0]; |
I1 = x[1] ^ k[1]; |
I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | |
((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | |
((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | |
((uint32_t) SBOX4((I0 ) & 0xFF) ); |
I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | |
((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | |
((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | |
((uint32_t) SBOX1((I1 ) & 0xFF) ); |
I0 ^= (I1 << 8) | (I1 >> 24); |
I1 ^= (I0 << 16) | (I0 >> 16); |
I0 ^= (I1 >> 8) | (I1 << 24); |
I1 ^= (I0 >> 8) | (I0 << 24); |
z[0] ^= I1; |
z[1] ^= I0; |
} |
void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) |
{ |
CAMELLIA_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); |
} |
void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); |
} |
/* |
* Camellia key schedule (encryption) |
*/ |
int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, |
const unsigned char *key, |
unsigned int keybits ) |
{ |
int idx; |
size_t i; |
uint32_t *RK; |
unsigned char t[64]; |
uint32_t SIGMA[6][2]; |
uint32_t KC[16]; |
uint32_t TK[20]; |
CAMELLIA_VALIDATE_RET( ctx != NULL ); |
CAMELLIA_VALIDATE_RET( key != NULL ); |
RK = ctx->rk; |
memset( t, 0, 64 ); |
memset( RK, 0, sizeof(ctx->rk) ); |
switch( keybits ) |
{ |
case 128: ctx->nr = 3; idx = 0; break; |
case 192: |
case 256: ctx->nr = 4; idx = 1; break; |
default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); |
} |
for( i = 0; i < keybits / 8; ++i ) |
t[i] = key[i]; |
if( keybits == 192 ) { |
for( i = 0; i < 8; i++ ) |
t[24 + i] = ~t[16 + i]; |
} |
/* |
* Prepare SIGMA values |
*/ |
for( i = 0; i < 6; i++ ) { |
GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); |
GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); |
} |
/* |
* Key storage in KC |
* Order: KL, KR, KA, KB |
*/ |
memset( KC, 0, sizeof(KC) ); |
/* Store KL, KR */ |
for( i = 0; i < 8; i++ ) |
GET_UINT32_BE( KC[i], t, i * 4 ); |
/* Generate KA */ |
for( i = 0; i < 4; ++i ) |
KC[8 + i] = KC[i] ^ KC[4 + i]; |
camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); |
camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); |
for( i = 0; i < 4; ++i ) |
KC[8 + i] ^= KC[i]; |
camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); |
camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); |
if( keybits > 128 ) { |
/* Generate KB */ |
for( i = 0; i < 4; ++i ) |
KC[12 + i] = KC[4 + i] ^ KC[8 + i]; |
camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); |
camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); |
} |
/* |
* Generating subkeys |
*/ |
/* Manipulating KL */ |
SHIFT_AND_PLACE( idx, 0 ); |
/* Manipulating KR */ |
if( keybits > 128 ) { |
SHIFT_AND_PLACE( idx, 1 ); |
} |
/* Manipulating KA */ |
SHIFT_AND_PLACE( idx, 2 ); |
/* Manipulating KB */ |
if( keybits > 128 ) { |
SHIFT_AND_PLACE( idx, 3 ); |
} |
/* Do transpositions */ |
for( i = 0; i < 20; i++ ) { |
if( transposes[idx][i] != -1 ) { |
RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; |
} |
} |
return( 0 ); |
} |
/* |
* Camellia key schedule (decryption) |
*/ |
int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, |
const unsigned char *key, |
unsigned int keybits ) |
{ |
int idx, ret; |
size_t i; |
mbedtls_camellia_context cty; |
uint32_t *RK; |
uint32_t *SK; |
CAMELLIA_VALIDATE_RET( ctx != NULL ); |
CAMELLIA_VALIDATE_RET( key != NULL ); |
mbedtls_camellia_init( &cty ); |
/* Also checks keybits */ |
if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) |
goto exit; |
ctx->nr = cty.nr; |
idx = ( ctx->nr == 4 ); |
RK = ctx->rk; |
SK = cty.rk + 24 * 2 + 8 * idx * 2; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) |
{ |
*RK++ = *SK++; |
*RK++ = *SK++; |
} |
SK -= 2; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
exit: |
mbedtls_camellia_free( &cty ); |
return( ret ); |
} |
/* |
* Camellia-ECB block encryption/decryption |
*/ |
int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, |
int mode, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
int NR; |
uint32_t *RK, X[4]; |
CAMELLIA_VALIDATE_RET( ctx != NULL ); |
CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || |
mode == MBEDTLS_CAMELLIA_DECRYPT ); |
CAMELLIA_VALIDATE_RET( input != NULL ); |
CAMELLIA_VALIDATE_RET( output != NULL ); |
( (void) mode ); |
NR = ctx->nr; |
RK = ctx->rk; |
GET_UINT32_BE( X[0], input, 0 ); |
GET_UINT32_BE( X[1], input, 4 ); |
GET_UINT32_BE( X[2], input, 8 ); |
GET_UINT32_BE( X[3], input, 12 ); |
X[0] ^= *RK++; |
X[1] ^= *RK++; |
X[2] ^= *RK++; |
X[3] ^= *RK++; |
while( NR ) { |
--NR; |
camellia_feistel( X, RK, X + 2 ); |
RK += 2; |
camellia_feistel( X + 2, RK, X ); |
RK += 2; |
camellia_feistel( X, RK, X + 2 ); |
RK += 2; |
camellia_feistel( X + 2, RK, X ); |
RK += 2; |
camellia_feistel( X, RK, X + 2 ); |
RK += 2; |
camellia_feistel( X + 2, RK, X ); |
RK += 2; |
if( NR ) { |
FL(X[0], X[1], RK[0], RK[1]); |
RK += 2; |
FLInv(X[2], X[3], RK[0], RK[1]); |
RK += 2; |
} |
} |
X[2] ^= *RK++; |
X[3] ^= *RK++; |
X[0] ^= *RK++; |
X[1] ^= *RK++; |
PUT_UINT32_BE( X[2], output, 0 ); |
PUT_UINT32_BE( X[3], output, 4 ); |
PUT_UINT32_BE( X[0], output, 8 ); |
PUT_UINT32_BE( X[1], output, 12 ); |
return( 0 ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* Camellia-CBC buffer encryption/decryption |
*/ |
int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int i; |
unsigned char temp[16]; |
CAMELLIA_VALIDATE_RET( ctx != NULL ); |
CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || |
mode == MBEDTLS_CAMELLIA_DECRYPT ); |
CAMELLIA_VALIDATE_RET( iv != NULL ); |
CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); |
CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); |
if( length % 16 ) |
return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); |
if( mode == MBEDTLS_CAMELLIA_DECRYPT ) |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, 16 ); |
mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); |
for( i = 0; i < 16; i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, 16 ); |
input += 16; |
output += 16; |
length -= 16; |
} |
} |
else |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < 16; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); |
memcpy( iv, output, 16 ); |
input += 16; |
output += 16; |
length -= 16; |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
/* |
* Camellia-CFB128 buffer encryption/decryption |
*/ |
int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, |
int mode, |
size_t length, |
size_t *iv_off, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c; |
size_t n; |
CAMELLIA_VALIDATE_RET( ctx != NULL ); |
CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || |
mode == MBEDTLS_CAMELLIA_DECRYPT ); |
CAMELLIA_VALIDATE_RET( iv != NULL ); |
CAMELLIA_VALIDATE_RET( iv_off != NULL ); |
CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); |
CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); |
n = *iv_off; |
if( n >= 16 ) |
return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); |
if( mode == MBEDTLS_CAMELLIA_DECRYPT ) |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); |
c = *input++; |
*output++ = (unsigned char)( c ^ iv[n] ); |
iv[n] = (unsigned char) c; |
n = ( n + 1 ) & 0x0F; |
} |
} |
else |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); |
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); |
n = ( n + 1 ) & 0x0F; |
} |
} |
*iv_off = n; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* Camellia-CTR buffer encryption/decryption |
*/ |
int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, |
size_t length, |
size_t *nc_off, |
unsigned char nonce_counter[16], |
unsigned char stream_block[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c, i; |
size_t n; |
CAMELLIA_VALIDATE_RET( ctx != NULL ); |
CAMELLIA_VALIDATE_RET( nonce_counter != NULL ); |
CAMELLIA_VALIDATE_RET( stream_block != NULL ); |
CAMELLIA_VALIDATE_RET( nc_off != NULL ); |
CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); |
CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); |
n = *nc_off; |
if( n >= 16 ) |
return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); |
while( length-- ) |
{ |
if( n == 0 ) { |
mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, |
stream_block ); |
for( i = 16; i > 0; i-- ) |
if( ++nonce_counter[i - 1] != 0 ) |
break; |
} |
c = *input++; |
*output++ = (unsigned char)( c ^ stream_block[n] ); |
n = ( n + 1 ) & 0x0F; |
} |
*nc_off = n; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#endif /* !MBEDTLS_CAMELLIA_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* Camellia test vectors from: |
* |
* http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: |
* http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt |
* http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt |
* (For each bitlength: Key 0, Nr 39) |
*/ |
#define CAMELLIA_TESTS_ECB 2 |
static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = |
{ |
{ |
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } |
}, |
{ |
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, |
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } |
}, |
{ |
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, |
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } |
}, |
}; |
static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = |
{ |
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, |
{ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } |
}; |
static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = |
{ |
{ |
{ 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, |
0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, |
{ 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, |
0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } |
}, |
{ |
{ 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, |
0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, |
{ 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, |
0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } |
}, |
{ |
{ 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, |
0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, |
{ 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, |
0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } |
} |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#define CAMELLIA_TESTS_CBC 3 |
static const unsigned char camellia_test_cbc_key[3][32] = |
{ |
{ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, |
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } |
, |
{ 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, |
0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, |
0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } |
, |
{ 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, |
0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, |
0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, |
0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } |
}; |
static const unsigned char camellia_test_cbc_iv[16] = |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } |
; |
static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = |
{ |
{ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, |
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, |
{ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, |
0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, |
{ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, |
0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } |
}; |
static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = |
{ |
{ |
{ 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, |
0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, |
{ 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, |
0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, |
{ 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, |
0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } |
}, |
{ |
{ 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, |
0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, |
{ 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, |
0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, |
{ 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, |
0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } |
}, |
{ |
{ 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, |
0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, |
{ 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, |
0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, |
{ 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, |
0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } |
} |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* Camellia-CTR test vectors from: |
* |
* http://www.faqs.org/rfcs/rfc5528.html |
*/ |
static const unsigned char camellia_test_ctr_key[3][16] = |
{ |
{ 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, |
0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, |
{ 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, |
0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, |
{ 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, |
0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } |
}; |
static const unsigned char camellia_test_ctr_nonce_counter[3][16] = |
{ |
{ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, |
{ 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, |
0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, |
{ 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, |
0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } |
}; |
static const unsigned char camellia_test_ctr_pt[3][48] = |
{ |
{ 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, |
0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, |
0x20, 0x21, 0x22, 0x23 } |
}; |
static const unsigned char camellia_test_ctr_ct[3][48] = |
{ |
{ 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, |
0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, |
{ 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, |
0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, |
0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, |
0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, |
{ 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, |
0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, |
0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, |
0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, |
0xDF, 0x50, 0x86, 0x96 } |
}; |
static const int camellia_test_ctr_len[3] = |
{ 16, 32, 36 }; |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
/* |
* Checkup routine |
*/ |
int mbedtls_camellia_self_test( int verbose ) |
{ |
int i, j, u, v; |
unsigned char key[32]; |
unsigned char buf[64]; |
unsigned char src[16]; |
unsigned char dst[16]; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
unsigned char iv[16]; |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
size_t offset, len; |
unsigned char nonce_counter[16]; |
unsigned char stream_block[16]; |
#endif |
mbedtls_camellia_context ctx; |
memset( key, 0, 32 ); |
for( j = 0; j < 6; j++ ) { |
u = j >> 1; |
v = j & 1; |
if( verbose != 0 ) |
mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, |
(v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); |
for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { |
memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); |
if( v == MBEDTLS_CAMELLIA_DECRYPT ) { |
mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); |
memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); |
memcpy( dst, camellia_test_ecb_plain[i], 16 ); |
} else { /* MBEDTLS_CAMELLIA_ENCRYPT */ |
mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); |
memcpy( src, camellia_test_ecb_plain[i], 16 ); |
memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); |
} |
mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); |
if( memcmp( buf, dst, 16 ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* CBC mode |
*/ |
for( j = 0; j < 6; j++ ) |
{ |
u = j >> 1; |
v = j & 1; |
if( verbose != 0 ) |
mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, |
( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); |
memcpy( src, camellia_test_cbc_iv, 16 ); |
memcpy( dst, camellia_test_cbc_iv, 16 ); |
memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); |
if( v == MBEDTLS_CAMELLIA_DECRYPT ) { |
mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); |
} else { |
mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); |
} |
for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { |
if( v == MBEDTLS_CAMELLIA_DECRYPT ) { |
memcpy( iv , src, 16 ); |
memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); |
memcpy( dst, camellia_test_cbc_plain[i], 16 ); |
} else { /* MBEDTLS_CAMELLIA_ENCRYPT */ |
memcpy( iv , dst, 16 ); |
memcpy( src, camellia_test_cbc_plain[i], 16 ); |
memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); |
} |
mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); |
if( memcmp( buf, dst, 16 ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
/* |
* CTR mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
v = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", |
( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); |
memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); |
memcpy( key, camellia_test_ctr_key[u], 16 ); |
offset = 0; |
mbedtls_camellia_setkey_enc( &ctx, key, 128 ); |
if( v == MBEDTLS_CAMELLIA_DECRYPT ) |
{ |
len = camellia_test_ctr_len[u]; |
memcpy( buf, camellia_test_ctr_ct[u], len ); |
mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, |
buf, buf ); |
if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
} |
else |
{ |
len = camellia_test_ctr_len[u]; |
memcpy( buf, camellia_test_ctr_pt[u], len ); |
mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, |
buf, buf ); |
if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
/programs/develop/libraries/kos_mbedtls/library/ccm.c |
---|
0,0 → 1,547 |
/* |
* NIST SP800-38C compliant CCM implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* Definition of CCM: |
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf |
* RFC 3610 "Counter with CBC-MAC (CCM)" |
* |
* Related: |
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption" |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CCM_C) |
#include "mbedtls/ccm.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ |
#if !defined(MBEDTLS_CCM_ALT) |
#define CCM_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT ) |
#define CCM_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#define CCM_ENCRYPT 0 |
#define CCM_DECRYPT 1 |
/* |
* Initialize context |
*/ |
void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) |
{ |
CCM_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); |
} |
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, |
mbedtls_cipher_id_t cipher, |
const unsigned char *key, |
unsigned int keybits ) |
{ |
int ret; |
const mbedtls_cipher_info_t *cipher_info; |
CCM_VALIDATE_RET( ctx != NULL ); |
CCM_VALIDATE_RET( key != NULL ); |
cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); |
if( cipher_info == NULL ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
if( cipher_info->block_size != 16 ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
mbedtls_cipher_free( &ctx->cipher_ctx ); |
if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, |
MBEDTLS_ENCRYPT ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
/* |
* Free context |
*/ |
void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_cipher_free( &ctx->cipher_ctx ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); |
} |
/* |
* Macros for common operations. |
* Results in smaller compiled code than static inline functions. |
*/ |
/* |
* Update the CBC-MAC state in y using a block in b |
* (Always using b as the source helps the compiler optimise a bit better.) |
*/ |
#define UPDATE_CBC_MAC \ |
for( i = 0; i < 16; i++ ) \ |
y[i] ^= b[i]; \ |
\ |
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ |
return( ret ); |
/* |
* Encrypt or decrypt a partial block with CTR |
* Warning: using b for temporary storage! src and dst must not be b! |
* This avoids allocating one more 16 bytes buffer while allowing src == dst. |
*/ |
#define CTR_CRYPT( dst, src, len ) \ |
do \ |
{ \ |
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \ |
16, b, &olen ) ) != 0 ) \ |
{ \ |
return( ret ); \ |
} \ |
\ |
for( i = 0; i < (len); i++ ) \ |
(dst)[i] = (src)[i] ^ b[i]; \ |
} while( 0 ) |
/* |
* Authenticated encryption or decryption |
*/ |
static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *add, size_t add_len, |
const unsigned char *input, unsigned char *output, |
unsigned char *tag, size_t tag_len ) |
{ |
int ret; |
unsigned char i; |
unsigned char q; |
size_t len_left, olen; |
unsigned char b[16]; |
unsigned char y[16]; |
unsigned char ctr[16]; |
const unsigned char *src; |
unsigned char *dst; |
/* |
* Check length requirements: SP800-38C A.1 |
* Additional requirement: a < 2^16 - 2^8 to simplify the code. |
* 'length' checked later (when writing it to the first block) |
* |
* Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). |
*/ |
if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
/* Also implies q is within bounds */ |
if( iv_len < 7 || iv_len > 13 ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
if( add_len > 0xFF00 ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
q = 16 - 1 - (unsigned char) iv_len; |
/* |
* First block B_0: |
* 0 .. 0 flags |
* 1 .. iv_len nonce (aka iv) |
* iv_len+1 .. 15 length |
* |
* With flags as (bits): |
* 7 0 |
* 6 add present? |
* 5 .. 3 (t - 2) / 2 |
* 2 .. 0 q - 1 |
*/ |
b[0] = 0; |
b[0] |= ( add_len > 0 ) << 6; |
b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; |
b[0] |= q - 1; |
memcpy( b + 1, iv, iv_len ); |
for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) |
b[15-i] = (unsigned char)( len_left & 0xFF ); |
if( len_left > 0 ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
/* Start CBC-MAC with first block */ |
memset( y, 0, 16 ); |
UPDATE_CBC_MAC; |
/* |
* If there is additional data, update CBC-MAC with |
* add_len, add, 0 (padding to a block boundary) |
*/ |
if( add_len > 0 ) |
{ |
size_t use_len; |
len_left = add_len; |
src = add; |
memset( b, 0, 16 ); |
b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); |
b[1] = (unsigned char)( ( add_len ) & 0xFF ); |
use_len = len_left < 16 - 2 ? len_left : 16 - 2; |
memcpy( b + 2, src, use_len ); |
len_left -= use_len; |
src += use_len; |
UPDATE_CBC_MAC; |
while( len_left > 0 ) |
{ |
use_len = len_left > 16 ? 16 : len_left; |
memset( b, 0, 16 ); |
memcpy( b, src, use_len ); |
UPDATE_CBC_MAC; |
len_left -= use_len; |
src += use_len; |
} |
} |
/* |
* Prepare counter block for encryption: |
* 0 .. 0 flags |
* 1 .. iv_len nonce (aka iv) |
* iv_len+1 .. 15 counter (initially 1) |
* |
* With flags as (bits): |
* 7 .. 3 0 |
* 2 .. 0 q - 1 |
*/ |
ctr[0] = q - 1; |
memcpy( ctr + 1, iv, iv_len ); |
memset( ctr + 1 + iv_len, 0, q ); |
ctr[15] = 1; |
/* |
* Authenticate and {en,de}crypt the message. |
* |
* The only difference between encryption and decryption is |
* the respective order of authentication and {en,de}cryption. |
*/ |
len_left = length; |
src = input; |
dst = output; |
while( len_left > 0 ) |
{ |
size_t use_len = len_left > 16 ? 16 : len_left; |
if( mode == CCM_ENCRYPT ) |
{ |
memset( b, 0, 16 ); |
memcpy( b, src, use_len ); |
UPDATE_CBC_MAC; |
} |
CTR_CRYPT( dst, src, use_len ); |
if( mode == CCM_DECRYPT ) |
{ |
memset( b, 0, 16 ); |
memcpy( b, dst, use_len ); |
UPDATE_CBC_MAC; |
} |
dst += use_len; |
src += use_len; |
len_left -= use_len; |
/* |
* Increment counter. |
* No need to check for overflow thanks to the length check above. |
*/ |
for( i = 0; i < q; i++ ) |
if( ++ctr[15-i] != 0 ) |
break; |
} |
/* |
* Authentication: reset counter and crypt/mask internal tag |
*/ |
for( i = 0; i < q; i++ ) |
ctr[15-i] = 0; |
CTR_CRYPT( y, y, 16 ); |
memcpy( tag, y, tag_len ); |
return( 0 ); |
} |
/* |
* Authenticated encryption |
*/ |
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *add, size_t add_len, |
const unsigned char *input, unsigned char *output, |
unsigned char *tag, size_t tag_len ) |
{ |
CCM_VALIDATE_RET( ctx != NULL ); |
CCM_VALIDATE_RET( iv != NULL ); |
CCM_VALIDATE_RET( add_len == 0 || add != NULL ); |
CCM_VALIDATE_RET( length == 0 || input != NULL ); |
CCM_VALIDATE_RET( length == 0 || output != NULL ); |
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, |
add, add_len, input, output, tag, tag_len ) ); |
} |
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *add, size_t add_len, |
const unsigned char *input, unsigned char *output, |
unsigned char *tag, size_t tag_len ) |
{ |
CCM_VALIDATE_RET( ctx != NULL ); |
CCM_VALIDATE_RET( iv != NULL ); |
CCM_VALIDATE_RET( add_len == 0 || add != NULL ); |
CCM_VALIDATE_RET( length == 0 || input != NULL ); |
CCM_VALIDATE_RET( length == 0 || output != NULL ); |
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
if( tag_len == 0 ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add, |
add_len, input, output, tag, tag_len ) ); |
} |
/* |
* Authenticated decryption |
*/ |
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *add, size_t add_len, |
const unsigned char *input, unsigned char *output, |
const unsigned char *tag, size_t tag_len ) |
{ |
int ret; |
unsigned char check_tag[16]; |
unsigned char i; |
int diff; |
CCM_VALIDATE_RET( ctx != NULL ); |
CCM_VALIDATE_RET( iv != NULL ); |
CCM_VALIDATE_RET( add_len == 0 || add != NULL ); |
CCM_VALIDATE_RET( length == 0 || input != NULL ); |
CCM_VALIDATE_RET( length == 0 || output != NULL ); |
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, |
iv, iv_len, add, add_len, |
input, output, check_tag, tag_len ) ) != 0 ) |
{ |
return( ret ); |
} |
/* Check tag in "constant-time" */ |
for( diff = 0, i = 0; i < tag_len; i++ ) |
diff |= tag[i] ^ check_tag[i]; |
if( diff != 0 ) |
{ |
mbedtls_platform_zeroize( output, length ); |
return( MBEDTLS_ERR_CCM_AUTH_FAILED ); |
} |
return( 0 ); |
} |
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *add, size_t add_len, |
const unsigned char *input, unsigned char *output, |
const unsigned char *tag, size_t tag_len ) |
{ |
CCM_VALIDATE_RET( ctx != NULL ); |
CCM_VALIDATE_RET( iv != NULL ); |
CCM_VALIDATE_RET( add_len == 0 || add != NULL ); |
CCM_VALIDATE_RET( length == 0 || input != NULL ); |
CCM_VALIDATE_RET( length == 0 || output != NULL ); |
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
if( tag_len == 0 ) |
return( MBEDTLS_ERR_CCM_BAD_INPUT ); |
return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add, |
add_len, input, output, tag, tag_len ) ); |
} |
#endif /* !MBEDTLS_CCM_ALT */ |
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) |
/* |
* Examples 1 to 3 from SP800-38C Appendix C |
*/ |
#define NB_TESTS 3 |
#define CCM_SELFTEST_PT_MAX_LEN 24 |
#define CCM_SELFTEST_CT_MAX_LEN 32 |
/* |
* The data is the same for all tests, only the used length changes |
*/ |
static const unsigned char key[] = { |
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f |
}; |
static const unsigned char iv[] = { |
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
0x18, 0x19, 0x1a, 0x1b |
}; |
static const unsigned char ad[] = { |
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
0x10, 0x11, 0x12, 0x13 |
}; |
static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = { |
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, |
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, |
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
}; |
static const size_t iv_len [NB_TESTS] = { 7, 8, 12 }; |
static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; |
static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; |
static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; |
static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { |
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, |
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, |
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, |
0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, |
{ 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, |
0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, |
0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, |
0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } |
}; |
int mbedtls_ccm_self_test( int verbose ) |
{ |
mbedtls_ccm_context ctx; |
/* |
* Some hardware accelerators require the input and output buffers |
* would be in RAM, because the flash is not accessible. |
* Use buffers on the stack to hold the test vectors data. |
*/ |
unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; |
unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; |
size_t i; |
int ret; |
mbedtls_ccm_init( &ctx ); |
if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " CCM: setup failed" ); |
return( 1 ); |
} |
for( i = 0; i < NB_TESTS; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); |
memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); |
memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); |
memcpy( plaintext, msg, msg_len[i] ); |
ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], |
iv, iv_len[i], ad, add_len[i], |
plaintext, ciphertext, |
ciphertext + msg_len[i], tag_len[i] ); |
if( ret != 0 || |
memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); |
ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], |
iv, iv_len[i], ad, add_len[i], |
ciphertext, plaintext, |
ciphertext + msg_len[i], tag_len[i] ); |
if( ret != 0 || |
memcmp( plaintext, msg, msg_len[i] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
mbedtls_ccm_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ |
#endif /* MBEDTLS_CCM_C */ |
/programs/develop/libraries/kos_mbedtls/library/certs.c |
---|
0,0 → 1,1755 |
/* |
* X.509 test certificates |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#include "mbedtls/certs.h" |
#if defined(MBEDTLS_CERTS_C) |
/* |
* Test CA Certificates |
* |
* We define test CA certificates for each choice of the following parameters: |
* - PEM or DER encoding |
* - SHA-1 or SHA-256 hash |
* - RSA or EC key |
* |
* Things to add: |
* - multiple EC curve types |
* |
*/ |
/* This is taken from tests/data_files/test-ca2.crt */ |
/* BEGIN FILE string macro TEST_CA_CRT_EC_PEM tests/data_files/test-ca2.crt */ |
#define TEST_CA_CRT_EC_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIICBDCCAYigAwIBAgIJAMFD4n5iQ8zoMAwGCCqGSM49BAMCBQAwPjELMAkGA1UE\r\n" \ |
"BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ |
"IEVDIENBMB4XDTE5MDIxMDE0NDQwMFoXDTI5MDIxMDE0NDQwMFowPjELMAkGA1UE\r\n" \ |
"BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ |
"IEVDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEw9orNEE3WC+HVv78ibopQ0tO\r\n" \ |
"4G7DDldTMzlY1FK0kZU5CyPfXxckYkj8GpUpziwth8KIUoCv1mqrId240xxuWLjK\r\n" \ |
"6LJpjvNBrSnDtF91p0dv1RkpVWmaUzsgtGYWYDMeo1AwTjAMBgNVHRMEBTADAQH/\r\n" \ |
"MB0GA1UdDgQWBBSdbSAkSQE/K8t4tRm8fiTJ2/s2fDAfBgNVHSMEGDAWgBSdbSAk\r\n" \ |
"SQE/K8t4tRm8fiTJ2/s2fDAMBggqhkjOPQQDAgUAA2gAMGUCMFHKrjAPpHB0BN1a\r\n" \ |
"LH8TwcJ3vh0AxeKZj30mRdOKBmg/jLS3rU3g8VQBHpn8sOTTBwIxANxPO5AerimZ\r\n" \ |
"hCjMe0d4CTHf1gFZMF70+IqEP+o5VHsIp2Cqvflb0VGWFC5l9a4cQg==\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This is generated from tests/data_files/test-ca2.crt.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_CA_CRT_EC_DER tests/data_files/test-ca2.crt.der */ |
#define TEST_CA_CRT_EC_DER { \ |
0x30, 0x82, 0x02, 0x04, 0x30, 0x82, 0x01, 0x88, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, \ |
0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, \ |
0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ |
0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ |
0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ |
0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ |
0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ |
0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, \ |
0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, \ |
0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, \ |
0x30, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ |
0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ |
0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ |
0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ |
0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ |
0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, \ |
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, \ |
0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, \ |
0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, \ |
0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, \ |
0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, \ |
0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, \ |
0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, \ |
0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, \ |
0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, \ |
0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c, \ |
0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, \ |
0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, \ |
0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, \ |
0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x1f, 0x06, 0x03, 0x55, \ |
0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, \ |
0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, \ |
0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ |
0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, \ |
0x30, 0x51, 0xca, 0xae, 0x30, 0x0f, 0xa4, 0x70, 0x74, 0x04, 0xdd, 0x5a, \ |
0x2c, 0x7f, 0x13, 0xc1, 0xc2, 0x77, 0xbe, 0x1d, 0x00, 0xc5, 0xe2, 0x99, \ |
0x8f, 0x7d, 0x26, 0x45, 0xd3, 0x8a, 0x06, 0x68, 0x3f, 0x8c, 0xb4, 0xb7, \ |
0xad, 0x4d, 0xe0, 0xf1, 0x54, 0x01, 0x1e, 0x99, 0xfc, 0xb0, 0xe4, 0xd3, \ |
0x07, 0x02, 0x31, 0x00, 0xdc, 0x4f, 0x3b, 0x90, 0x1e, 0xae, 0x29, 0x99, \ |
0x84, 0x28, 0xcc, 0x7b, 0x47, 0x78, 0x09, 0x31, 0xdf, 0xd6, 0x01, 0x59, \ |
0x30, 0x5e, 0xf4, 0xf8, 0x8a, 0x84, 0x3f, 0xea, 0x39, 0x54, 0x7b, 0x08, \ |
0xa7, 0x60, 0xaa, 0xbd, 0xf9, 0x5b, 0xd1, 0x51, 0x96, 0x14, 0x2e, 0x65, \ |
0xf5, 0xae, 0x1c, 0x42 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/test-ca2.key.enc */ |
/* BEGIN FILE string macro TEST_CA_KEY_EC_PEM tests/data_files/test-ca2.key.enc */ |
#define TEST_CA_KEY_EC_PEM \ |
"-----BEGIN EC PRIVATE KEY-----\r\n" \ |
"Proc-Type: 4,ENCRYPTED\r\n" \ |
"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" \ |
"\r\n" \ |
"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" \ |
"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" \ |
"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" \ |
"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" \ |
"-----END EC PRIVATE KEY-----\r\n" |
/* END FILE */ |
#define TEST_CA_PWD_EC_PEM "PolarSSLTest" |
/* This is generated from tests/data_files/test-ca2.key.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_CA_KEY_EC_DER tests/data_files/test-ca2.key.der */ |
#define TEST_CA_KEY_EC_DER { \ |
0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x83, 0xd9, 0x15, 0x0e, \ |
0xa0, 0x71, 0xf0, 0x57, 0x10, 0x33, 0xa3, 0x38, 0xb8, 0x86, 0xc1, 0xa6, \ |
0x11, 0x5d, 0x6d, 0xb4, 0x03, 0xe1, 0x29, 0x76, 0x45, 0xd7, 0x87, 0x6f, \ |
0x23, 0xab, 0x44, 0x20, 0xea, 0x64, 0x7b, 0x85, 0xb1, 0x76, 0xe7, 0x85, \ |
0x95, 0xaa, 0x74, 0xd6, 0xd1, 0xa4, 0x5e, 0xea, 0xa0, 0x07, 0x06, 0x05, \ |
0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xc3, \ |
0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, \ |
0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, \ |
0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, \ |
0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, \ |
0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, \ |
0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, \ |
0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, \ |
0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/test-ca-sha256.crt. */ |
/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA256_PEM tests/data_files/test-ca-sha256.crt */ |
#define TEST_CA_CRT_RSA_SHA256_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ |
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ |
"MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ |
"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ |
"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ |
"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ |
"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ |
"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ |
"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ |
"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ |
"UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ |
"MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBCwUA\r\n" \ |
"A4IBAQA4qFSCth2q22uJIdE4KGHJsJjVEfw2/xn+MkTvCMfxVrvmRvqCtjE4tKDl\r\n" \ |
"oK4MxFOek07oDZwvtAT9ijn1hHftTNS7RH9zd/fxNpfcHnMZXVC4w4DNA1fSANtW\r\n" \ |
"5sY1JB5Je9jScrsLSS+mAjyv0Ow3Hb2Bix8wu7xNNrV5fIf7Ubm+wt6SqEBxu3Kb\r\n" \ |
"+EfObAT4huf3czznhH3C17ed6NSbXwoXfby7stWUDeRJv08RaFOykf/Aae7bY5PL\r\n" \ |
"yTVrkAnikMntJ9YI+hNNYt3inqq11A5cN0+rVTst8UKCxzQ4GpvroSwPKTFkbMw4\r\n" \ |
"/anT1dVxr/BtwJfiESoK3/4CeXR1\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This is generated from tests/data_files/test-ca-sha256.crt.der |
* using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA256_DER tests/data_files/test-ca-sha256.crt.der */ |
#define TEST_CA_CRT_RSA_SHA256_DER { \ |
0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ |
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ |
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ |
0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ |
0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ |
0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ |
0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ |
0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ |
0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ |
0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ |
0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ |
0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ |
0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ |
0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ |
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ |
0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ |
0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ |
0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ |
0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ |
0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ |
0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ |
0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ |
0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ |
0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ |
0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ |
0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ |
0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ |
0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ |
0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ |
0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ |
0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ |
0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ |
0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ |
0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ |
0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ |
0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ |
0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ |
0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ |
0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ |
0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ |
0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ |
0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ |
0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ |
0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ |
0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ |
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, \ |
0x03, 0x82, 0x01, 0x01, 0x00, 0x38, 0xa8, 0x54, 0x82, 0xb6, 0x1d, 0xaa, \ |
0xdb, 0x6b, 0x89, 0x21, 0xd1, 0x38, 0x28, 0x61, 0xc9, 0xb0, 0x98, 0xd5, \ |
0x11, 0xfc, 0x36, 0xff, 0x19, 0xfe, 0x32, 0x44, 0xef, 0x08, 0xc7, 0xf1, \ |
0x56, 0xbb, 0xe6, 0x46, 0xfa, 0x82, 0xb6, 0x31, 0x38, 0xb4, 0xa0, 0xe5, \ |
0xa0, 0xae, 0x0c, 0xc4, 0x53, 0x9e, 0x93, 0x4e, 0xe8, 0x0d, 0x9c, 0x2f, \ |
0xb4, 0x04, 0xfd, 0x8a, 0x39, 0xf5, 0x84, 0x77, 0xed, 0x4c, 0xd4, 0xbb, \ |
0x44, 0x7f, 0x73, 0x77, 0xf7, 0xf1, 0x36, 0x97, 0xdc, 0x1e, 0x73, 0x19, \ |
0x5d, 0x50, 0xb8, 0xc3, 0x80, 0xcd, 0x03, 0x57, 0xd2, 0x00, 0xdb, 0x56, \ |
0xe6, 0xc6, 0x35, 0x24, 0x1e, 0x49, 0x7b, 0xd8, 0xd2, 0x72, 0xbb, 0x0b, \ |
0x49, 0x2f, 0xa6, 0x02, 0x3c, 0xaf, 0xd0, 0xec, 0x37, 0x1d, 0xbd, 0x81, \ |
0x8b, 0x1f, 0x30, 0xbb, 0xbc, 0x4d, 0x36, 0xb5, 0x79, 0x7c, 0x87, 0xfb, \ |
0x51, 0xb9, 0xbe, 0xc2, 0xde, 0x92, 0xa8, 0x40, 0x71, 0xbb, 0x72, 0x9b, \ |
0xf8, 0x47, 0xce, 0x6c, 0x04, 0xf8, 0x86, 0xe7, 0xf7, 0x73, 0x3c, 0xe7, \ |
0x84, 0x7d, 0xc2, 0xd7, 0xb7, 0x9d, 0xe8, 0xd4, 0x9b, 0x5f, 0x0a, 0x17, \ |
0x7d, 0xbc, 0xbb, 0xb2, 0xd5, 0x94, 0x0d, 0xe4, 0x49, 0xbf, 0x4f, 0x11, \ |
0x68, 0x53, 0xb2, 0x91, 0xff, 0xc0, 0x69, 0xee, 0xdb, 0x63, 0x93, 0xcb, \ |
0xc9, 0x35, 0x6b, 0x90, 0x09, 0xe2, 0x90, 0xc9, 0xed, 0x27, 0xd6, 0x08, \ |
0xfa, 0x13, 0x4d, 0x62, 0xdd, 0xe2, 0x9e, 0xaa, 0xb5, 0xd4, 0x0e, 0x5c, \ |
0x37, 0x4f, 0xab, 0x55, 0x3b, 0x2d, 0xf1, 0x42, 0x82, 0xc7, 0x34, 0x38, \ |
0x1a, 0x9b, 0xeb, 0xa1, 0x2c, 0x0f, 0x29, 0x31, 0x64, 0x6c, 0xcc, 0x38, \ |
0xfd, 0xa9, 0xd3, 0xd5, 0xd5, 0x71, 0xaf, 0xf0, 0x6d, 0xc0, 0x97, 0xe2, \ |
0x11, 0x2a, 0x0a, 0xdf, 0xfe, 0x02, 0x79, 0x74, 0x75 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/test-ca-sha1.crt. */ |
/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA1_PEM tests/data_files/test-ca-sha1.crt */ |
#define TEST_CA_CRT_RSA_SHA1_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ |
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ |
"MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ |
"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ |
"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ |
"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ |
"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ |
"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ |
"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ |
"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ |
"UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ |
"MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n" \ |
"A4IBAQB0ZiNRFdia6kskaPnhrqejIRq8YMEGAf2oIPnyZ78xoyERgc35lHGyMtsL\r\n" \ |
"hWicNjP4d/hS9As4j5KA2gdNGi5ETA1X7SowWOGsryivSpMSHVy1+HdfWlsYQOzm\r\n" \ |
"8o+faQNUm8XzPVmttfAVspxeHSxJZ36Oo+QWZ5wZlCIEyjEdLUId+Tm4Bz3B5jRD\r\n" \ |
"zZa/SaqDokq66N2zpbgKKAl3GU2O++fBqP2dSkdQykmTxhLLWRN8FJqhYATyQntZ\r\n" \ |
"0QSi3W9HfSZPnFTcPIXeoiPd2pLlxt1hZu8dws2LTXE63uP6MM4LHvWxiuJaWkP/\r\n" \ |
"mtxyUALj2pQxRitopORFQdn7AOY5\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This is taken from tests/data_files/test-ca-sha1.crt.der. */ |
/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER tests/data_files/test-ca-sha1.crt.der */ |
#define TEST_CA_CRT_RSA_SHA1_DER { \ |
0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ |
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ |
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ |
0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ |
0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ |
0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ |
0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ |
0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ |
0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ |
0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ |
0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ |
0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ |
0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ |
0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ |
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ |
0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ |
0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ |
0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ |
0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ |
0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ |
0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ |
0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ |
0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ |
0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ |
0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ |
0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ |
0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ |
0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ |
0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ |
0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ |
0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ |
0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ |
0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ |
0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ |
0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ |
0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ |
0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ |
0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ |
0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ |
0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ |
0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ |
0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ |
0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ |
0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ |
0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ |
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \ |
0x03, 0x82, 0x01, 0x01, 0x00, 0x74, 0x66, 0x23, 0x51, 0x15, 0xd8, 0x9a, \ |
0xea, 0x4b, 0x24, 0x68, 0xf9, 0xe1, 0xae, 0xa7, 0xa3, 0x21, 0x1a, 0xbc, \ |
0x60, 0xc1, 0x06, 0x01, 0xfd, 0xa8, 0x20, 0xf9, 0xf2, 0x67, 0xbf, 0x31, \ |
0xa3, 0x21, 0x11, 0x81, 0xcd, 0xf9, 0x94, 0x71, 0xb2, 0x32, 0xdb, 0x0b, \ |
0x85, 0x68, 0x9c, 0x36, 0x33, 0xf8, 0x77, 0xf8, 0x52, 0xf4, 0x0b, 0x38, \ |
0x8f, 0x92, 0x80, 0xda, 0x07, 0x4d, 0x1a, 0x2e, 0x44, 0x4c, 0x0d, 0x57, \ |
0xed, 0x2a, 0x30, 0x58, 0xe1, 0xac, 0xaf, 0x28, 0xaf, 0x4a, 0x93, 0x12, \ |
0x1d, 0x5c, 0xb5, 0xf8, 0x77, 0x5f, 0x5a, 0x5b, 0x18, 0x40, 0xec, 0xe6, \ |
0xf2, 0x8f, 0x9f, 0x69, 0x03, 0x54, 0x9b, 0xc5, 0xf3, 0x3d, 0x59, 0xad, \ |
0xb5, 0xf0, 0x15, 0xb2, 0x9c, 0x5e, 0x1d, 0x2c, 0x49, 0x67, 0x7e, 0x8e, \ |
0xa3, 0xe4, 0x16, 0x67, 0x9c, 0x19, 0x94, 0x22, 0x04, 0xca, 0x31, 0x1d, \ |
0x2d, 0x42, 0x1d, 0xf9, 0x39, 0xb8, 0x07, 0x3d, 0xc1, 0xe6, 0x34, 0x43, \ |
0xcd, 0x96, 0xbf, 0x49, 0xaa, 0x83, 0xa2, 0x4a, 0xba, 0xe8, 0xdd, 0xb3, \ |
0xa5, 0xb8, 0x0a, 0x28, 0x09, 0x77, 0x19, 0x4d, 0x8e, 0xfb, 0xe7, 0xc1, \ |
0xa8, 0xfd, 0x9d, 0x4a, 0x47, 0x50, 0xca, 0x49, 0x93, 0xc6, 0x12, 0xcb, \ |
0x59, 0x13, 0x7c, 0x14, 0x9a, 0xa1, 0x60, 0x04, 0xf2, 0x42, 0x7b, 0x59, \ |
0xd1, 0x04, 0xa2, 0xdd, 0x6f, 0x47, 0x7d, 0x26, 0x4f, 0x9c, 0x54, 0xdc, \ |
0x3c, 0x85, 0xde, 0xa2, 0x23, 0xdd, 0xda, 0x92, 0xe5, 0xc6, 0xdd, 0x61, \ |
0x66, 0xef, 0x1d, 0xc2, 0xcd, 0x8b, 0x4d, 0x71, 0x3a, 0xde, 0xe3, 0xfa, \ |
0x30, 0xce, 0x0b, 0x1e, 0xf5, 0xb1, 0x8a, 0xe2, 0x5a, 0x5a, 0x43, 0xff, \ |
0x9a, 0xdc, 0x72, 0x50, 0x02, 0xe3, 0xda, 0x94, 0x31, 0x46, 0x2b, 0x68, \ |
0xa4, 0xe4, 0x45, 0x41, 0xd9, 0xfb, 0x00, 0xe6, 0x39 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/test-ca.key */ |
/* BEGIN FILE string macro TEST_CA_KEY_RSA_PEM tests/data_files/test-ca.key */ |
#define TEST_CA_KEY_RSA_PEM \ |
"-----BEGIN RSA PRIVATE KEY-----\r\n" \ |
"Proc-Type: 4,ENCRYPTED\r\n" \ |
"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" \ |
"\r\n" \ |
"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" \ |
"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" \ |
"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" \ |
"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" \ |
"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" \ |
"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" \ |
"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" \ |
"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" \ |
"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" \ |
"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" \ |
"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" \ |
"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" \ |
"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" \ |
"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" \ |
"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" \ |
"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" \ |
"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" \ |
"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" \ |
"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" \ |
"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" \ |
"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" \ |
"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" \ |
"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" \ |
"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" \ |
"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" \ |
"-----END RSA PRIVATE KEY-----\r\n" |
/* END FILE */ |
#define TEST_CA_PWD_RSA_PEM "PolarSSLTest" |
/* This was generated from test-ca.key.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_CA_KEY_RSA_DER tests/data_files/test-ca.key.der */ |
#define TEST_CA_KEY_RSA_DER { \ |
0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ |
0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, 0x86, 0xde, \ |
0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, 0x99, 0xd4, \ |
0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, 0x9b, 0xc5, \ |
0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, 0xc0, 0x8d, \ |
0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, 0x93, 0xe8, \ |
0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, 0xe7, 0x40, \ |
0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, 0xf9, 0x3e, \ |
0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, 0x29, 0x00, \ |
0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, 0xbd, 0x83, \ |
0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, 0x60, 0xc3, \ |
0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, 0x32, 0xbe, \ |
0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, 0xfb, 0xf5, \ |
0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, 0xee, 0xe2, \ |
0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, 0x47, 0xb1, \ |
0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, 0xf1, 0x79, \ |
0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, 0x6f, 0x27, \ |
0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, 0xa1, 0x30, \ |
0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, 0x28, 0xd1, \ |
0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, 0x09, 0xea, \ |
0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, 0xc9, 0xab, \ |
0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, 0x9e, 0x99, \ |
0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ |
0x00, 0x3f, 0xf7, 0x07, 0xd3, 0x34, 0x6f, 0xdb, 0xc9, 0x37, 0xb7, 0x84, \ |
0xdc, 0x37, 0x45, 0xe1, 0x63, 0xad, 0xb8, 0xb6, 0x75, 0xb1, 0xc7, 0x35, \ |
0xb4, 0x77, 0x2a, 0x5b, 0x77, 0xf9, 0x7e, 0xe0, 0xc1, 0xa3, 0xd1, 0xb7, \ |
0xcb, 0xa9, 0x5a, 0xc1, 0x87, 0xda, 0x5a, 0xfa, 0x17, 0xe4, 0xd5, 0x38, \ |
0x03, 0xde, 0x68, 0x98, 0x81, 0xec, 0xb5, 0xf2, 0x2a, 0x8d, 0xe9, 0x2c, \ |
0xf3, 0xa6, 0xe5, 0x32, 0x17, 0x7f, 0x33, 0x81, 0xe8, 0x38, 0x72, 0xd5, \ |
0x9c, 0xfa, 0x4e, 0xfb, 0x26, 0xf5, 0x15, 0x0b, 0xaf, 0x84, 0x66, 0xab, \ |
0x02, 0xe0, 0x18, 0xd5, 0x91, 0x7c, 0xd6, 0x8f, 0xc9, 0x4b, 0x76, 0x08, \ |
0x2b, 0x1d, 0x81, 0x68, 0x30, 0xe1, 0xfa, 0x70, 0x6c, 0x13, 0x4e, 0x10, \ |
0x03, 0x35, 0x3e, 0xc5, 0xca, 0x58, 0x20, 0x8a, 0x21, 0x18, 0x38, 0xa0, \ |
0x0f, 0xed, 0xc4, 0xbb, 0x45, 0x6f, 0xf5, 0x84, 0x5b, 0xb0, 0xcf, 0x4e, \ |
0x9d, 0x58, 0x13, 0x6b, 0x35, 0x35, 0x69, 0xa1, 0xd2, 0xc4, 0xf2, 0xc1, \ |
0x48, 0x04, 0x20, 0x51, 0xb9, 0x6b, 0xa4, 0x5d, 0xa5, 0x4b, 0x84, 0x88, \ |
0x43, 0x48, 0x99, 0x2c, 0xbb, 0xa4, 0x97, 0xd6, 0xd6, 0x18, 0xf6, 0xec, \ |
0x5c, 0xd1, 0x31, 0x49, 0xc9, 0xf2, 0x8f, 0x0b, 0x4d, 0xef, 0x09, 0x02, \ |
0xfe, 0x7d, 0xfd, 0xbb, 0xaf, 0x2b, 0x83, 0x94, 0x22, 0xc4, 0xa7, 0x3e, \ |
0x66, 0xf5, 0xe0, 0x57, 0xdc, 0xf2, 0xed, 0x2c, 0x3e, 0x81, 0x74, 0x76, \ |
0x1e, 0x96, 0x6f, 0x74, 0x1e, 0x32, 0x0e, 0x14, 0x31, 0xd0, 0x74, 0xf0, \ |
0xf4, 0x07, 0xbd, 0xc3, 0xd1, 0x22, 0xc2, 0xa8, 0x95, 0x92, 0x06, 0x7f, \ |
0x43, 0x02, 0x91, 0xbc, 0xdd, 0x23, 0x01, 0x89, 0x94, 0x20, 0x44, 0x64, \ |
0xf5, 0x1d, 0x67, 0xd2, 0x8f, 0xe8, 0x69, 0xa5, 0x29, 0x25, 0xe6, 0x50, \ |
0x9c, 0xe3, 0xe9, 0xcb, 0x75, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x29, 0x3e, \ |
0xaa, 0x6b, 0xd5, 0x59, 0x1e, 0x9c, 0xe6, 0x47, 0xd5, 0xb6, 0xd7, 0xe3, \ |
0xf1, 0x8e, 0x9e, 0xe9, 0x83, 0x5f, 0x10, 0x9f, 0x63, 0xec, 0x04, 0x44, \ |
0xcc, 0x3f, 0xf8, 0xd9, 0x3a, 0x17, 0xe0, 0x4f, 0xfe, 0xd8, 0x4d, 0xcd, \ |
0x46, 0x54, 0x74, 0xbf, 0x0a, 0xc4, 0x67, 0x9c, 0xa7, 0xd8, 0x89, 0x65, \ |
0x4c, 0xfd, 0x58, 0x2a, 0x47, 0x0f, 0xf4, 0x37, 0xb6, 0x55, 0xb0, 0x1d, \ |
0xed, 0xa7, 0x39, 0xfc, 0x4f, 0xa3, 0xc4, 0x75, 0x3a, 0xa3, 0x98, 0xa7, \ |
0x45, 0xf5, 0x66, 0xcb, 0x7c, 0x65, 0xfb, 0x80, 0x23, 0xe6, 0xff, 0xfd, \ |
0x99, 0x1f, 0x8e, 0x6b, 0xff, 0x5e, 0x93, 0x66, 0xdf, 0x6c, 0x6f, 0xc3, \ |
0xf6, 0x38, 0x2e, 0xff, 0x69, 0xb5, 0xac, 0xae, 0xbb, 0xc6, 0x71, 0x16, \ |
0x6b, 0xd0, 0xf8, 0x22, 0xd9, 0xf8, 0xa2, 0x72, 0x20, 0xd2, 0xe2, 0x3a, \ |
0x70, 0x4b, 0xde, 0xab, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xda, 0x51, 0x9b, \ |
0xb8, 0xb2, 0x2a, 0x14, 0x75, 0x58, 0x40, 0x8d, 0x27, 0x70, 0xfa, 0x31, \ |
0x48, 0xb0, 0x20, 0x21, 0x34, 0xfa, 0x4c, 0x57, 0xa8, 0x11, 0x88, 0xf3, \ |
0xa7, 0xae, 0x21, 0xe9, 0xb6, 0x2b, 0xd1, 0xcd, 0xa7, 0xf8, 0xd8, 0x0c, \ |
0x8a, 0x76, 0x22, 0x35, 0x44, 0xce, 0x3f, 0x25, 0x29, 0x83, 0x7d, 0x79, \ |
0xa7, 0x31, 0xd6, 0xec, 0xb2, 0xbf, 0xda, 0x34, 0xb6, 0xf6, 0xb2, 0x3b, \ |
0xf3, 0x78, 0x5a, 0x04, 0x83, 0x33, 0x3e, 0xa2, 0xe2, 0x81, 0x82, 0x13, \ |
0xd4, 0x35, 0x17, 0x63, 0x9b, 0x9e, 0xc4, 0x8d, 0x91, 0x4c, 0x03, 0x77, \ |
0xc7, 0x71, 0x5b, 0xee, 0x83, 0x6d, 0xd5, 0x78, 0x88, 0xf6, 0x2c, 0x79, \ |
0xc2, 0x4a, 0xb4, 0x79, 0x90, 0x70, 0xbf, 0xdf, 0x34, 0x56, 0x96, 0x71, \ |
0xe3, 0x0e, 0x68, 0x91, 0xbc, 0xea, 0xcb, 0x33, 0xc0, 0xbe, 0x45, 0xd7, \ |
0xfc, 0x30, 0xfd, 0x01, 0x3b, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x9f, 0x2a, \ |
0xb7, 0x38, 0x19, 0xc7, 0x17, 0x95, 0x73, 0x78, 0xae, 0xf5, 0xcb, 0x75, \ |
0x83, 0x7f, 0x19, 0x4b, 0xcb, 0x86, 0xfb, 0x4a, 0x15, 0x9a, 0xb6, 0x17, \ |
0x04, 0x49, 0x07, 0x8d, 0xf6, 0x66, 0x4a, 0x06, 0xf6, 0x05, 0xa7, 0xdf, \ |
0x66, 0x82, 0x3c, 0xff, 0xb6, 0x1d, 0x57, 0x89, 0x33, 0x5f, 0x9c, 0x05, \ |
0x75, 0x7f, 0xf3, 0x5d, 0xdc, 0x34, 0x65, 0x72, 0x85, 0x22, 0xa4, 0x14, \ |
0x1b, 0x41, 0xc3, 0xe4, 0xd0, 0x9e, 0x69, 0xd5, 0xeb, 0x38, 0x74, 0x70, \ |
0x43, 0xdc, 0xd9, 0x50, 0xe4, 0x97, 0x6d, 0x73, 0xd6, 0xfb, 0xc8, 0xa7, \ |
0xfa, 0xb4, 0xc2, 0xc4, 0x9d, 0x5d, 0x0c, 0xd5, 0x9f, 0x79, 0xb3, 0x54, \ |
0xc2, 0xb7, 0x6c, 0x3d, 0x7d, 0xcb, 0x2d, 0xf8, 0xc4, 0xf3, 0x78, 0x5a, \ |
0x33, 0x2a, 0xb8, 0x0c, 0x6d, 0x06, 0xfa, 0xf2, 0x62, 0xd3, 0x42, 0xd0, \ |
0xbd, 0xc8, 0x4a, 0xa5, 0x0d, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xa9, 0x90, \ |
0x15, 0xde, 0xbf, 0x2c, 0xc4, 0x8d, 0x9d, 0xfb, 0xa1, 0xc2, 0xe4, 0x83, \ |
0xe3, 0x79, 0x65, 0x22, 0xd3, 0xb7, 0x49, 0x6c, 0x4d, 0x94, 0x1f, 0x22, \ |
0xb1, 0x60, 0xe7, 0x3a, 0x00, 0xb1, 0x38, 0xa2, 0xab, 0x0f, 0xb4, 0x6c, \ |
0xaa, 0xe7, 0x9e, 0x34, 0xe3, 0x7c, 0x40, 0x78, 0x53, 0xb2, 0xf9, 0x23, \ |
0xea, 0xa0, 0x9a, 0xea, 0x60, 0xc8, 0x8f, 0xa6, 0xaf, 0xdf, 0x29, 0x09, \ |
0x4b, 0x06, 0x1e, 0x31, 0xad, 0x17, 0xda, 0xd8, 0xd1, 0xe9, 0x33, 0xab, \ |
0x5b, 0x18, 0x08, 0x5b, 0x87, 0xf8, 0xa5, 0x1f, 0xfd, 0xbb, 0xdc, 0xd8, \ |
0xed, 0x97, 0x57, 0xe4, 0xc3, 0x73, 0xd6, 0xf0, 0x9e, 0x01, 0xa6, 0x9b, \ |
0x48, 0x8e, 0x7a, 0xb4, 0xbb, 0xe5, 0x88, 0x91, 0xc5, 0x2a, 0xdf, 0x4b, \ |
0xba, 0xd0, 0x8b, 0x3e, 0x03, 0x97, 0x77, 0x2f, 0x47, 0x7e, 0x51, 0x0c, \ |
0xae, 0x65, 0x8d, 0xde, 0x87, 0x02, 0x81, 0x80, 0x20, 0x24, 0x0f, 0xd2, \ |
0xaf, 0xc2, 0x28, 0x3b, 0x97, 0x20, 0xb2, 0x92, 0x49, 0xeb, 0x09, 0x68, \ |
0x40, 0xb2, 0xbe, 0xd1, 0xc3, 0x83, 0x94, 0x34, 0x38, 0xd6, 0xc9, 0xec, \ |
0x34, 0x09, 0xf9, 0x41, 0x6d, 0x5c, 0x42, 0x94, 0xf7, 0x04, 0xfc, 0x32, \ |
0x39, 0x69, 0xbc, 0x1c, 0xfb, 0x3e, 0x61, 0x98, 0xc0, 0x80, 0xd8, 0x36, \ |
0x47, 0xc3, 0x6d, 0xc2, 0x2e, 0xe7, 0x81, 0x2a, 0x17, 0x34, 0x64, 0x30, \ |
0x4e, 0x96, 0xbb, 0x26, 0x16, 0xb9, 0x41, 0x36, 0xfe, 0x8a, 0xd6, 0x53, \ |
0x7c, 0xaa, 0xec, 0x39, 0x42, 0x50, 0xef, 0xe3, 0xb3, 0x01, 0x28, 0x32, \ |
0xca, 0x6d, 0xf5, 0x9a, 0x1e, 0x9f, 0x37, 0xbe, 0xfe, 0x38, 0x20, 0x22, \ |
0x91, 0x8c, 0xcd, 0x95, 0x02, 0xf2, 0x4d, 0x6f, 0x1a, 0xb4, 0x43, 0xf0, \ |
0x19, 0xdf, 0x65, 0xc0, 0x92, 0xe7, 0x9d, 0x2f, 0x09, 0xe7, 0xec, 0x69, \ |
0xa8, 0xc2, 0x8f, 0x0d \ |
} |
/* END FILE */ |
/* |
* Test server Certificates |
* |
* Test server certificates are defined for each choice |
* of the following parameters: |
* - PEM or DER encoding |
* - SHA-1 or SHA-256 hash |
* - RSA or EC key |
* |
* Things to add: |
* - multiple EC curve types |
*/ |
/* This is taken from tests/data_files/server5.crt. */ |
/* BEGIN FILE string macro TEST_SRV_CRT_EC_PEM tests/data_files/server5.crt */ |
#define TEST_SRV_CRT_EC_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" \ |
"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" \ |
"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ |
"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" \ |
"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" \ |
"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" \ |
"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" \ |
"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" \ |
"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" \ |
"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" \ |
"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" \ |
"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This is generated from tests/data_files/server5.crt.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_SRV_CRT_EC_DER tests/data_files/server5.crt.der */ |
#define TEST_SRV_CRT_EC_DER { \ |
0x30, 0x82, 0x02, 0x1f, 0x30, 0x82, 0x01, 0xa5, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x01, 0x09, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ |
0x3d, 0x04, 0x03, 0x02, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ |
0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ |
0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ |
0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, \ |
0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ |
0x31, 0x33, 0x30, 0x39, 0x32, 0x34, 0x31, 0x35, 0x35, 0x32, 0x30, 0x34, \ |
0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x39, 0x32, 0x32, 0x31, 0x35, 0x35, \ |
0x32, 0x30, 0x34, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ |
0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ |
0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ |
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59, \ |
0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, \ |
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, \ |
0x04, 0x37, 0xcc, 0x56, 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, \ |
0x59, 0x2d, 0xff, 0x20, 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, \ |
0xad, 0x14, 0xb5, 0xf7, 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, \ |
0xd8, 0x23, 0x11, 0xff, 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, \ |
0x8a, 0x88, 0xc2, 0x6b, 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, \ |
0x01, 0xc8, 0xb4, 0xed, 0xff, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30, \ |
0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, \ |
0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0x61, 0xa5, \ |
0x8f, 0xd4, 0x07, 0xd9, 0xd7, 0x82, 0x01, 0x0c, 0xe5, 0x65, 0x7f, 0x8c, \ |
0x63, 0x46, 0xa7, 0x13, 0xbe, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, \ |
0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, \ |
0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, \ |
0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ |
0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ |
0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ |
0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ |
0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, \ |
0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09, \ |
0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0a, 0x06, \ |
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00, \ |
0x30, 0x65, 0x02, 0x31, 0x00, 0x9a, 0x2c, 0x5c, 0xd7, 0xa6, 0xdb, 0xa2, \ |
0xe5, 0x64, 0x0d, 0xf0, 0xb9, 0x4e, 0xdd, 0xd7, 0x61, 0xd6, 0x13, 0x31, \ |
0xc7, 0xab, 0x73, 0x80, 0xbb, 0xd3, 0xd3, 0x73, 0x13, 0x54, 0xad, 0x92, \ |
0x0b, 0x5d, 0xab, 0xd0, 0xbc, 0xf7, 0xae, 0x2f, 0xe6, 0xa1, 0x21, 0x29, \ |
0x35, 0x95, 0xaa, 0x3e, 0x39, 0x02, 0x30, 0x21, 0x36, 0x7f, 0x9d, 0xc6, \ |
0x5d, 0xc6, 0x0b, 0xab, 0x27, 0xf2, 0x25, 0x1d, 0x3b, 0xf1, 0xcf, 0xf1, \ |
0x35, 0x25, 0x14, 0xe7, 0xe5, 0xf1, 0x97, 0xb5, 0x59, 0xe3, 0x5e, 0x15, \ |
0x7c, 0x66, 0xb9, 0x90, 0x7b, 0xc7, 0x01, 0x10, 0x4f, 0x73, 0xc6, 0x00, \ |
0x21, 0x52, 0x2a, 0x0e, 0xf1, 0xc7, 0xd5 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/server5.key. */ |
/* BEGIN FILE string macro TEST_SRV_KEY_EC_PEM tests/data_files/server5.key */ |
#define TEST_SRV_KEY_EC_PEM \ |
"-----BEGIN EC PRIVATE KEY-----\r\n" \ |
"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" \ |
"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" \ |
"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" \ |
"-----END EC PRIVATE KEY-----\r\n" |
/* END FILE */ |
/* This is generated from tests/data_files/server5.key.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_SRV_KEY_EC_DER tests/data_files/server5.key.der */ |
#define TEST_SRV_KEY_EC_DER { \ |
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf1, 0x2a, 0x13, 0x20, 0x76, \ |
0x02, 0x70, 0xa8, 0x3c, 0xbf, 0xfd, 0x53, 0xf6, 0x03, 0x1e, 0xf7, 0x6a, \ |
0x5d, 0x86, 0xc8, 0xa2, 0x04, 0xf2, 0xc3, 0x0c, 0xa9, 0xeb, 0xf5, 0x1f, \ |
0x0f, 0x0e, 0xa7, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ |
0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x37, 0xcc, 0x56, \ |
0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, 0x59, 0x2d, 0xff, 0x20, \ |
0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, 0xad, 0x14, 0xb5, 0xf7, \ |
0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, 0xd8, 0x23, 0x11, 0xff, \ |
0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, 0x8a, 0x88, 0xc2, 0x6b, \ |
0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, 0x01, 0xc8, 0xb4, 0xed, \ |
0xff \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/server2-sha256.crt. */ |
/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA256_PEM tests/data_files/server2-sha256.crt */ |
#define TEST_SRV_CRT_RSA_SHA256_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ |
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ |
"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ |
"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ |
"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ |
"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ |
"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ |
"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ |
"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ |
"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ |
"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ |
"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\r\n" \ |
"Pqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\r\n" \ |
"HoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\r\n" \ |
"1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\r\n" \ |
"a1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\r\n" \ |
"e3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\r\n" \ |
"pMZqLmbBm/7WPLc=\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This is taken from tests/data_files/server2-sha256.crt.der. */ |
/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA256_DER tests/data_files/server2-sha256.crt.der */ |
#define TEST_SRV_CRT_RSA_SHA256_DER { \ |
0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ |
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ |
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ |
0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ |
0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ |
0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ |
0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ |
0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ |
0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ |
0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ |
0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ |
0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ |
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ |
0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ |
0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ |
0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ |
0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ |
0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ |
0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ |
0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ |
0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ |
0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ |
0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ |
0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ |
0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ |
0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ |
0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ |
0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ |
0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ |
0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ |
0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ |
0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ |
0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ |
0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ |
0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ |
0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ |
0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ |
0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ |
0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ |
0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ |
0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ |
0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ |
0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ |
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, \ |
0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0x3a, 0xe4, 0x52, 0x61, \ |
0x3e, 0xa7, 0xa5, 0xef, 0x32, 0x67, 0x80, 0x72, 0x07, 0x26, 0xba, 0xa3, \ |
0xff, 0x05, 0x40, 0xc4, 0x60, 0x05, 0x39, 0x31, 0x77, 0xf7, 0xa5, 0xca, \ |
0x01, 0x31, 0x80, 0xa7, 0xe1, 0xd1, 0x0a, 0xa2, 0x7c, 0xd5, 0x1c, 0xba, \ |
0xd0, 0x23, 0x4a, 0xd6, 0x30, 0xf3, 0x93, 0xc7, 0x6f, 0xe8, 0xce, 0x94, \ |
0x1e, 0x84, 0xbb, 0x44, 0x81, 0x62, 0x33, 0xff, 0x6b, 0x5d, 0x00, 0x9b, \ |
0x25, 0xf8, 0x8f, 0x0f, 0x9c, 0x4c, 0x4d, 0xe8, 0xd9, 0xa7, 0x99, 0xf9, \ |
0x51, 0x81, 0xc0, 0x9b, 0x1b, 0x31, 0x0d, 0xa6, 0xb3, 0x7c, 0x0e, 0x45, \ |
0xb8, 0x18, 0x64, 0x7e, 0x89, 0x0a, 0x2b, 0xa8, 0xc3, 0xe0, 0x4a, 0xbd, \ |
0xd4, 0x2f, 0x78, 0xc4, 0x62, 0x9b, 0xe9, 0x7e, 0x3f, 0x56, 0x46, 0x8f, \ |
0x17, 0xb7, 0x2a, 0xa0, 0x10, 0x70, 0xfd, 0xb1, 0xf1, 0x6b, 0x05, 0xdc, \ |
0xd1, 0x41, 0x0f, 0x8e, 0xa6, 0xb2, 0x88, 0x1a, 0x42, 0x61, 0x4f, 0xeb, \ |
0x26, 0x85, 0x59, 0x80, 0xba, 0x85, 0x54, 0xfe, 0xcf, 0xc7, 0x7b, 0x2f, \ |
0x6b, 0x59, 0xce, 0xac, 0xdc, 0x7c, 0xac, 0xf3, 0xc8, 0xd6, 0x12, 0x7e, \ |
0x64, 0xe8, 0x3c, 0x99, 0xa8, 0x8f, 0x4f, 0x11, 0xd9, 0x9c, 0x15, 0x4b, \ |
0x6a, 0x44, 0x92, 0x2d, 0x0c, 0xbf, 0xb1, 0x67, 0x96, 0xc9, 0xac, 0xce, \ |
0xd5, 0x19, 0xeb, 0x6f, 0x18, 0xeb, 0x6e, 0x04, 0x2d, 0x60, 0xac, 0xf4, \ |
0x7b, 0x79, 0xf0, 0x1a, 0x9b, 0xb5, 0xc3, 0x5d, 0xef, 0x7d, 0xc9, 0x05, \ |
0x99, 0x44, 0x81, 0x84, 0x75, 0xc7, 0xec, 0x00, 0x12, 0xfc, 0x7a, 0x4a, \ |
0x0b, 0x82, 0x07, 0xec, 0x6d, 0x86, 0x02, 0x4d, 0xfe, 0x9f, 0xc8, 0x92, \ |
0x48, 0xde, 0xf5, 0xb1, 0x9c, 0xe9, 0xc6, 0x89, 0xd0, 0xc1, 0x56, 0xe8, \ |
0xa4, 0xc6, 0x6a, 0x2e, 0x66, 0xc1, 0x9b, 0xfe, 0xd6, 0x3c, 0xb7 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/server2.crt. */ |
/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM tests/data_files/server2.crt */ |
#define TEST_SRV_CRT_RSA_SHA1_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ |
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ |
"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ |
"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ |
"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ |
"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ |
"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ |
"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ |
"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ |
"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ |
"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ |
"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n" \ |
"cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n" \ |
"O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n" \ |
"KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n" \ |
"iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n" \ |
"HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n" \ |
"Awgk0+4m0T25cNs=\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This is taken from tests/data_files/server2.crt.der. */ |
/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER tests/data_files/server2.crt.der */ |
#define TEST_SRV_CRT_RSA_SHA1_DER { \ |
0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ |
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ |
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ |
0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ |
0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ |
0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ |
0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ |
0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ |
0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ |
0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ |
0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ |
0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ |
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ |
0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ |
0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ |
0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ |
0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ |
0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ |
0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ |
0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ |
0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ |
0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ |
0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ |
0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ |
0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ |
0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ |
0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ |
0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ |
0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ |
0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ |
0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ |
0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ |
0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ |
0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ |
0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ |
0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ |
0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ |
0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ |
0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ |
0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ |
0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ |
0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ |
0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ |
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \ |
0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x99, 0x25, 0x83, 0x74, 0x38, \ |
0x70, 0x1e, 0xef, 0xec, 0x1c, 0xec, 0xc4, 0xcf, 0xef, 0x2f, 0x22, 0x9c, \ |
0x70, 0xee, 0xa8, 0xa7, 0x4f, 0xe0, 0x67, 0x33, 0x38, 0x82, 0x1b, 0x8b, \ |
0xab, 0x66, 0x37, 0xda, 0x49, 0x74, 0xb0, 0xce, 0xa4, 0x48, 0xd5, 0x14, \ |
0x99, 0xdb, 0xae, 0xab, 0x7b, 0xbf, 0xf8, 0x69, 0x94, 0x64, 0xdd, 0x80, \ |
0x3b, 0xfe, 0xdc, 0xf8, 0x7c, 0x3b, 0x84, 0x31, 0x44, 0x22, 0xf6, 0x64, \ |
0xf7, 0xc6, 0x81, 0x1a, 0x30, 0x8b, 0xaa, 0x7d, 0xc3, 0x9a, 0x01, 0xc8, \ |
0xbf, 0xc4, 0xe8, 0x43, 0xae, 0xe7, 0x7a, 0x59, 0x50, 0xc7, 0x1d, 0x94, \ |
0x8f, 0x7d, 0x3d, 0x3d, 0xd8, 0x23, 0x36, 0x2f, 0xeb, 0xf4, 0x73, 0x9c, \ |
0x28, 0xd0, 0x18, 0x3d, 0xb0, 0x5c, 0x83, 0xa3, 0x09, 0x19, 0x65, 0xa3, \ |
0xd9, 0x32, 0x3a, 0xbc, 0xd6, 0x9c, 0x7a, 0x2a, 0x2c, 0xfc, 0x38, 0x4e, \ |
0x63, 0x1e, 0x55, 0xd2, 0x3e, 0x67, 0x7e, 0xa4, 0x89, 0xfe, 0x99, 0xd4, \ |
0xd2, 0x0f, 0x48, 0x82, 0x7d, 0x8b, 0x02, 0x18, 0x18, 0xa4, 0x62, 0x44, \ |
0x88, 0x43, 0x3d, 0xc1, 0x6e, 0xe1, 0x10, 0xc9, 0x30, 0x9a, 0x4d, 0x21, \ |
0xfe, 0xca, 0x99, 0xb2, 0xb2, 0x6c, 0x18, 0x7e, 0x58, 0xb0, 0x5f, 0xd5, \ |
0x4e, 0x14, 0xaa, 0xfc, 0x95, 0x4e, 0xd5, 0xed, 0xa6, 0x64, 0x7d, 0xaf, \ |
0xae, 0xec, 0x99, 0x28, 0x95, 0x41, 0xab, 0xef, 0x2d, 0x0c, 0xd6, 0x29, \ |
0x1e, 0x42, 0xba, 0xb5, 0x2c, 0x95, 0x61, 0x08, 0x73, 0x22, 0xdd, 0xd2, \ |
0xb4, 0xc2, 0x56, 0x28, 0xc9, 0x7f, 0xa3, 0x99, 0x36, 0x01, 0x8c, 0xfa, \ |
0xb5, 0x20, 0xb5, 0xeb, 0x8f, 0xb5, 0xa0, 0x6f, 0x8c, 0x2f, 0x72, 0xd6, \ |
0x83, 0xc5, 0xeb, 0x18, 0xa6, 0xbd, 0xd4, 0x7e, 0x14, 0x38, 0xa6, 0xa9, \ |
0x03, 0x08, 0x24, 0xd3, 0xee, 0x26, 0xd1, 0x3d, 0xb9, 0x70, 0xdb \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/server2.key. */ |
/* BEGIN FILE string macro TEST_SRV_KEY_RSA_PEM tests/data_files/server2.key */ |
#define TEST_SRV_KEY_RSA_PEM \ |
"-----BEGIN RSA PRIVATE KEY-----\r\n" \ |
"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" \ |
"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" \ |
"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" \ |
"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" \ |
"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" \ |
"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" \ |
"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" \ |
"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" \ |
"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" \ |
"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" \ |
"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" \ |
"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" \ |
"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" \ |
"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" \ |
"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" \ |
"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" \ |
"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" \ |
"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" \ |
"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" \ |
"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" \ |
"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" \ |
"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" \ |
"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" \ |
"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" \ |
"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" \ |
"-----END RSA PRIVATE KEY-----\r\n" |
/* END FILE */ |
/* This was generated from tests/data_files/server2.key.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_SRV_KEY_RSA_DER tests/data_files/server2.key.der */ |
#define TEST_SRV_KEY_RSA_DER { \ |
0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ |
0xc1, 0x4d, 0xa3, 0xdd, 0xe7, 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, \ |
0xb8, 0x99, 0xac, 0x0e, 0x78, 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, \ |
0x16, 0xd0, 0x5a, 0xe4, 0xcd, 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, \ |
0x96, 0xa7, 0x52, 0xb4, 0x90, 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, \ |
0xfc, 0xb6, 0x34, 0xac, 0x24, 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, \ |
0xb0, 0x28, 0x7d, 0xa1, 0xda, 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, \ |
0xfe, 0xc1, 0x04, 0x52, 0xb3, 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, \ |
0xd8, 0x90, 0xc1, 0x61, 0xb4, 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, \ |
0xab, 0x74, 0x5e, 0x07, 0x7d, 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, \ |
0xd9, 0x0d, 0x1c, 0x2d, 0x49, 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, \ |
0x0b, 0x8a, 0x4f, 0x69, 0x0c, 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, \ |
0x66, 0x7d, 0xae, 0x54, 0x2b, 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, \ |
0xc3, 0xcd, 0x40, 0x49, 0x08, 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, \ |
0x46, 0xbf, 0xd0, 0xb8, 0xaa, 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, \ |
0x1e, 0x44, 0x18, 0x0f, 0x0f, 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, \ |
0x18, 0xc6, 0x62, 0x2f, 0xc7, 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, \ |
0x27, 0x89, 0x29, 0x01, 0xc5, 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, \ |
0x4a, 0x0e, 0xef, 0xd6, 0xde, 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, \ |
0x7a, 0xc4, 0x02, 0x3c, 0x9a, 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, \ |
0xcb, 0x73, 0x4b, 0x52, 0x96, 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, \ |
0x39, 0x5a, 0xd3, 0x0f, 0xb0, 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, \ |
0x12, 0x01, 0x30, 0x97, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ |
0x01, 0x00, 0x97, 0x47, 0x44, 0xbc, 0x10, 0x81, 0xc5, 0x18, 0xe4, 0x59, \ |
0xfb, 0xe0, 0x2d, 0x3a, 0x0e, 0x9e, 0x10, 0xdc, 0x43, 0xfb, 0x15, 0x6c, \ |
0xd1, 0xfd, 0x48, 0x78, 0x6c, 0xf9, 0xed, 0x38, 0xe8, 0xdd, 0x09, 0xd7, \ |
0x5f, 0xb5, 0x41, 0x64, 0xd7, 0x63, 0xfa, 0x9d, 0x44, 0x0a, 0xf8, 0x42, \ |
0x13, 0xf1, 0xbb, 0x5e, 0x79, 0x20, 0x53, 0x98, 0x4b, 0x65, 0x7f, 0x86, \ |
0x67, 0x48, 0xe4, 0xcf, 0xfb, 0x6a, 0x24, 0xe2, 0x34, 0xbd, 0x14, 0x9d, \ |
0x2c, 0x16, 0xe2, 0xa4, 0x79, 0xd6, 0xa2, 0xec, 0x81, 0x43, 0x87, 0xbf, \ |
0x03, 0x5c, 0x88, 0x25, 0xd9, 0x41, 0xb6, 0xa5, 0xf1, 0x27, 0x52, 0x84, \ |
0xfe, 0x2b, 0x6e, 0x1d, 0x16, 0xcd, 0x73, 0x88, 0xf8, 0x90, 0xbf, 0x19, \ |
0xfe, 0xbe, 0xa9, 0xbf, 0x09, 0xd3, 0x23, 0x43, 0xd2, 0xc7, 0x61, 0x2a, \ |
0xb3, 0x4e, 0x3c, 0x61, 0xd4, 0xbd, 0xd8, 0xb4, 0xfa, 0xa8, 0x0b, 0xf8, \ |
0x7e, 0x56, 0xcd, 0x0f, 0x13, 0x27, 0xda, 0xe6, 0x3b, 0xb3, 0x8c, 0x9c, \ |
0x4b, 0x84, 0x3c, 0xc3, 0x52, 0x57, 0x9c, 0x27, 0x9a, 0x02, 0x76, 0x26, \ |
0x59, 0x82, 0x39, 0xc3, 0x13, 0xbe, 0x6e, 0xf4, 0x44, 0x2d, 0x1d, 0x8c, \ |
0x73, 0x3e, 0x43, 0x99, 0x59, 0xcb, 0xf2, 0x34, 0x72, 0x9a, 0x5e, 0xa5, \ |
0xeb, 0x9f, 0x36, 0x6d, 0x2b, 0xf9, 0xa2, 0xe7, 0xd1, 0x78, 0x52, 0x1b, \ |
0xc8, 0xf6, 0x5b, 0x41, 0x69, 0x57, 0x81, 0x89, 0xe9, 0xbb, 0xa1, 0xde, \ |
0x19, 0x37, 0x3b, 0x13, 0x5c, 0xca, 0x61, 0x01, 0x86, 0xff, 0xdf, 0x83, \ |
0x41, 0x49, 0x7f, 0xd6, 0xf4, 0x2e, 0x08, 0xfa, 0x90, 0xc2, 0x7c, 0xb4, \ |
0xb5, 0x0a, 0x17, 0xdb, 0x0e, 0x6d, 0x75, 0x8a, 0x5d, 0x31, 0xd5, 0x66, \ |
0xfb, 0x39, 0x0b, 0xb5, 0xb6, 0xa3, 0xcd, 0xd4, 0xef, 0x88, 0x92, 0x5a, \ |
0x4d, 0x6c, 0xcb, 0xea, 0x5b, 0x79, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x3a, \ |
0xf9, 0x25, 0x5e, 0x24, 0x37, 0x26, 0x40, 0x97, 0x2f, 0xe0, 0x4a, 0xba, \ |
0x52, 0x1b, 0x51, 0xaf, 0x84, 0x06, 0x32, 0x24, 0x0c, 0xcf, 0x44, 0xa8, \ |
0x77, 0xa7, 0xad, 0xb5, 0x8c, 0x58, 0xcc, 0xc8, 0x31, 0xb7, 0x0d, 0xbc, \ |
0x08, 0x8a, 0xe0, 0xa6, 0x8c, 0xc2, 0x73, 0xe5, 0x1a, 0x64, 0x92, 0xe8, \ |
0xed, 0x4c, 0x6f, 0x0b, 0xa6, 0xa7, 0xf3, 0x9a, 0xf5, 0x6f, 0x69, 0xca, \ |
0x3c, 0x22, 0xd0, 0x15, 0xa8, 0x20, 0x27, 0x41, 0xf8, 0x43, 0x42, 0x7f, \ |
0xb1, 0x93, 0xa1, 0x04, 0x85, 0xda, 0xa0, 0x1c, 0xd6, 0xc6, 0xf7, 0x8a, \ |
0x9e, 0xea, 0x5c, 0x78, 0xa7, 0x55, 0xc4, 0x6b, 0x05, 0x8b, 0xc0, 0x83, \ |
0xcb, 0xce, 0x83, 0x05, 0xf8, 0xb2, 0x16, 0x2b, 0xdf, 0x06, 0x3f, 0xb8, \ |
0xec, 0x16, 0xda, 0x43, 0x33, 0xc1, 0x8f, 0xb0, 0xb8, 0xac, 0xae, 0xd4, \ |
0x94, 0xb8, 0xda, 0x6f, 0x6a, 0xc3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0xae, \ |
0x00, 0xcd, 0xa0, 0x72, 0x1a, 0x05, 0x8a, 0xee, 0x2f, 0xd4, 0x71, 0x4b, \ |
0xf0, 0x3e, 0xe5, 0xc1, 0xe1, 0x29, 0x8b, 0xa6, 0x67, 0x30, 0x98, 0xe7, \ |
0x12, 0xef, 0xdd, 0x12, 0x01, 0x90, 0x24, 0x58, 0xf0, 0x76, 0x92, 0xe7, \ |
0x3d, 0xbb, 0x23, 0xe1, 0xce, 0xf9, 0xa1, 0xd4, 0x38, 0x1b, 0x3f, 0x20, \ |
0xb3, 0x0f, 0x65, 0x6a, 0x8f, 0x55, 0x57, 0x36, 0xee, 0xb2, 0x84, 0x44, \ |
0xfc, 0x91, 0x88, 0xe1, 0xa4, 0xdd, 0x3b, 0x4a, 0x40, 0x4d, 0x7c, 0x86, \ |
0xed, 0xe1, 0xb5, 0x42, 0xef, 0xb9, 0x61, 0xcd, 0x58, 0x19, 0x77, 0x02, \ |
0xae, 0x58, 0x80, 0xdb, 0x13, 0x3d, 0xc7, 0x1f, 0x9d, 0xed, 0xff, 0xac, \ |
0x98, 0xfc, 0xcd, 0xf9, 0x62, 0x04, 0x83, 0x91, 0x89, 0x0d, 0x86, 0x43, \ |
0x8c, 0x0c, 0xc7, 0x1b, 0x90, 0x4d, 0xbe, 0x2f, 0xc5, 0x7c, 0xcd, 0x42, \ |
0xf5, 0xd3, 0xad, 0x8e, 0xfd, 0x9d, 0x02, 0x81, 0x80, 0x17, 0x4b, 0x79, \ |
0x2a, 0x6c, 0x1b, 0x8d, 0x61, 0xc1, 0x85, 0xc5, 0x6a, 0x3b, 0x82, 0x1c, \ |
0x05, 0x5b, 0xcd, 0xdc, 0x12, 0x25, 0x73, 0x5b, 0x9e, 0xd9, 0x84, 0x57, \ |
0x10, 0x39, 0x71, 0x63, 0x96, 0xf4, 0xaf, 0xc3, 0x78, 0x5d, 0xc7, 0x8c, \ |
0x80, 0xa9, 0x96, 0xd7, 0xc3, 0x87, 0x02, 0x96, 0x71, 0x7e, 0x5f, 0x2e, \ |
0x3c, 0x36, 0xae, 0x59, 0x92, 0xd7, 0x3a, 0x09, 0x78, 0xb9, 0xea, 0x6f, \ |
0xc2, 0x16, 0x42, 0xdc, 0x4b, 0x96, 0xad, 0x2c, 0xb2, 0x20, 0x23, 0x61, \ |
0x2d, 0x8d, 0xb5, 0x02, 0x1e, 0xe1, 0x6c, 0x81, 0x01, 0x3c, 0x5d, 0xcb, \ |
0xdd, 0x9b, 0x0e, 0xc0, 0x2f, 0x94, 0x12, 0xb2, 0xfe, 0x75, 0x75, 0x8b, \ |
0x74, 0x1e, 0x7a, 0x26, 0x0c, 0xb7, 0x81, 0x96, 0x81, 0x79, 0x6e, 0xdb, \ |
0xbc, 0x3a, 0xc4, 0x9e, 0x87, 0x09, 0x6e, 0xa0, 0xa6, 0xec, 0x8b, 0xa4, \ |
0x85, 0x71, 0xce, 0x04, 0xaf, 0x02, 0x81, 0x81, 0x00, 0xc2, 0xa7, 0x47, \ |
0x07, 0x48, 0x6a, 0xc8, 0xd4, 0xb3, 0x20, 0xe1, 0x98, 0xee, 0xff, 0x5a, \ |
0x6f, 0x30, 0x7a, 0xa5, 0x47, 0x40, 0xdc, 0x16, 0x62, 0x42, 0xf1, 0x2c, \ |
0xdc, 0xb8, 0xc7, 0x55, 0xde, 0x07, 0x3c, 0x9d, 0xb1, 0xd0, 0xdf, 0x02, \ |
0x82, 0xb0, 0x48, 0x58, 0xe1, 0x34, 0xab, 0xcf, 0xb4, 0x85, 0x23, 0x26, \ |
0x78, 0x4f, 0x7a, 0x59, 0x6f, 0xfb, 0x8c, 0x3d, 0xdf, 0x3d, 0x6c, 0x02, \ |
0x47, 0x9c, 0xe5, 0x5e, 0x49, 0xf1, 0x05, 0x0b, 0x1f, 0xbf, 0x48, 0x0f, \ |
0xdc, 0x10, 0xb9, 0x3d, 0x1d, 0x10, 0x77, 0x2a, 0x73, 0xf9, 0xdf, 0xbd, \ |
0xcd, 0xf3, 0x1f, 0xeb, 0x6e, 0x64, 0xca, 0x2b, 0x78, 0x4f, 0xf8, 0x73, \ |
0xc2, 0x10, 0xef, 0x79, 0x95, 0x33, 0x1e, 0x79, 0x35, 0x09, 0xff, 0x88, \ |
0x1b, 0xb4, 0x3e, 0x4c, 0xe1, 0x27, 0x2e, 0x75, 0x80, 0x58, 0x11, 0x03, \ |
0x21, 0x23, 0x96, 0x9a, 0xb5, 0x02, 0x81, 0x80, 0x05, 0x12, 0x64, 0x71, \ |
0x83, 0x00, 0x1c, 0xfe, 0xef, 0x83, 0xea, 0xdd, 0x2c, 0xc8, 0x2c, 0x00, \ |
0x62, 0x1e, 0x8f, 0x3a, 0xdb, 0x1c, 0xab, 0xd6, 0x34, 0x8b, 0xd1, 0xb2, \ |
0x5a, 0x4f, 0x3d, 0x37, 0x38, 0x02, 0xe0, 0xd7, 0x70, 0xc1, 0xb0, 0x47, \ |
0xe0, 0x08, 0x1a, 0x84, 0xec, 0x48, 0xc5, 0x7c, 0x76, 0x83, 0x12, 0x67, \ |
0xab, 0x7c, 0x9f, 0x90, 0x97, 0xc8, 0x8f, 0x07, 0xf4, 0xb3, 0x60, 0xf2, \ |
0x3f, 0x49, 0x18, 0xdb, 0x2e, 0x94, 0x6b, 0x53, 0x9e, 0xa2, 0x63, 0xde, \ |
0x63, 0xd9, 0xab, 0x21, 0x2e, 0x2d, 0x0a, 0xe0, 0xd0, 0xe8, 0xba, 0xc4, \ |
0x4c, 0x1e, 0xa5, 0xf5, 0x51, 0xa8, 0xc4, 0x92, 0xf8, 0x7f, 0x21, 0xe7, \ |
0x65, 0xbf, 0x0b, 0xe6, 0x01, 0xaf, 0x9c, 0x1d, 0x5b, 0x6c, 0x3f, 0x1c, \ |
0x2f, 0xa6, 0x0f, 0x68, 0x38, 0x8e, 0x85, 0xc4, 0x6c, 0x78, 0x2f, 0x6f, \ |
0x06, 0x21, 0x2e, 0x56 \ |
} |
/* END FILE */ |
/* |
* Test client Certificates |
* |
* Test client certificates are defined for each choice |
* of the following parameters: |
* - PEM or DER encoding |
* - RSA or EC key |
* |
* Things to add: |
* - hash type |
* - multiple EC curve types |
*/ |
/* This is taken from tests/data_files/cli2.crt. */ |
/* BEGIN FILE string macro TEST_CLI_CRT_EC_PEM tests/data_files/cli2.crt */ |
#define TEST_CLI_CRT_EC_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIIB3zCCAWOgAwIBAgIBDTAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw\r\n" \ |
"DwYDVQQKDAhQb2xhclNTTDEcMBoGA1UEAwwTUG9sYXJTU0wgVGVzdCBFQyBDQTAe\r\n" \ |
"Fw0xOTAyMTAxNDQ0MDBaFw0yOTAyMTAxNDQ0MDBaMEExCzAJBgNVBAYTAk5MMREw\r\n" \ |
"DwYDVQQKDAhQb2xhclNTTDEfMB0GA1UEAwwWUG9sYXJTU0wgVGVzdCBDbGllbnQg\r\n" \ |
"MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFflrrFz39Osu5O4gf8Sru7mU6zO\r\n" \ |
"VVP2NA7MLuNjJQvfmOLzXGA2lsDVGBRw5X+f1UtFGOWwbNVc+JaPh3Cj5MejTTBL\r\n" \ |
"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMB8GA1Ud\r\n" \ |
"IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n" \ |
"AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n" \ |
"IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n" \ |
"a9Vk\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This is generated from tests/data_files/cli2.crt.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER tests/data_files/cli2.crt.der */ |
#define TEST_CLI_CRT_EC_DER { \ |
0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ |
0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ |
0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ |
0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ |
0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ |
0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ |
0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \ |
0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \ |
0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \ |
0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \ |
0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ |
0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ |
0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \ |
0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ |
0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \ |
0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ |
0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \ |
0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \ |
0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \ |
0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \ |
0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \ |
0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \ |
0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \ |
0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \ |
0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \ |
0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \ |
0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \ |
0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \ |
0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \ |
0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ |
0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \ |
0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \ |
0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \ |
0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \ |
0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \ |
0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \ |
0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \ |
0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \ |
0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \ |
0x6b, 0xd5, 0x64 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/cli2.key. */ |
/* BEGIN FILE string macro TEST_CLI_KEY_EC_PEM tests/data_files/cli2.key */ |
#define TEST_CLI_KEY_EC_PEM \ |
"-----BEGIN EC PRIVATE KEY-----\r\n" \ |
"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" \ |
"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" \ |
"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" \ |
"-----END EC PRIVATE KEY-----\r\n" |
/* END FILE */ |
/* This is generated from tests/data_files/cli2.key.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_CLI_KEY_EC_DER tests/data_files/cli2.key.der */ |
#define TEST_CLI_KEY_EC_DER { \ |
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, 0xf7, 0x86, 0x64, 0xf1, \ |
0x67, 0x7f, 0xe6, 0x64, 0x8d, 0xef, 0xca, 0x4e, 0xe9, 0xdd, 0x4d, 0xf0, \ |
0x05, 0xff, 0x96, 0x22, 0x8a, 0x7a, 0x84, 0x38, 0x64, 0x17, 0x32, 0x61, \ |
0x98, 0xb7, 0x2a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ |
0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, \ |
0xb1, 0x73, 0xdf, 0xd3, 0xac, 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, \ |
0xee, 0xe6, 0x53, 0xac, 0xce, 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, \ |
0xe3, 0x63, 0x25, 0x0b, 0xdf, 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, \ |
0xc0, 0xd5, 0x18, 0x14, 0x70, 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, \ |
0xe5, 0xb0, 0x6c, 0xd5, 0x5c, 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, \ |
0xc7 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/cli-rsa-sha256.crt. */ |
/* BEGIN FILE string macro TEST_CLI_CRT_RSA_PEM tests/data_files/cli-rsa-sha256.crt */ |
#define TEST_CLI_CRT_RSA_PEM \ |
"-----BEGIN CERTIFICATE-----\r\n" \ |
"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ |
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ |
"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" \ |
"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" \ |
"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" \ |
"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" \ |
"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" \ |
"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" \ |
"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" \ |
"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" \ |
"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" \ |
"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" \ |
"AQEAXidv1d4pLlBiKWED95rMycBdgDcgyNqJxakFkRfRyA2y1mlyTn7uBXRkNLY5\r\n" \ |
"ZFzK82GCjk2Q2OD4RZSCPAJJqLpHHU34t71ciffvy2KK81YvrxczRhMAE64i+qna\r\n" \ |
"yP3Td2XuWJR05PVPoSemsNELs9gWttdnYy3ce+EY2Y0n7Rsi7982EeLIAA7H6ca4\r\n" \ |
"2Es/NUH//JZJT32OP0doMxeDRA+vplkKqTLLWf7dX26LIriBkBaRCgR5Yv9LBPFc\r\n" \ |
"NOtpzu/LbrY7QFXKJMI+JXDudCsOn8KCmiA4d6Emisqfh3V3485l7HEQNcvLTxlD\r\n" \ |
"6zDQyi0/ykYUYZkwQTK1N2Nvlw==\r\n" \ |
"-----END CERTIFICATE-----\r\n" |
/* END FILE */ |
/* This was generated from tests/data_files/cli-rsa-sha256.crt.der |
using `xxd -i.` */ |
/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER tests/data_files/cli-rsa-sha256.crt.der */ |
#define TEST_CLI_CRT_RSA_DER { \ |
0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \ |
0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ |
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ |
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ |
0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ |
0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ |
0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ |
0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ |
0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ |
0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ |
0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ |
0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ |
0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ |
0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ |
0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \ |
0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \ |
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \ |
0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \ |
0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \ |
0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \ |
0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \ |
0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \ |
0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \ |
0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \ |
0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \ |
0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \ |
0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \ |
0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \ |
0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \ |
0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \ |
0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \ |
0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \ |
0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \ |
0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \ |
0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \ |
0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \ |
0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \ |
0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \ |
0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \ |
0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \ |
0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \ |
0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \ |
0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \ |
0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \ |
0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \ |
0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \ |
0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ |
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \ |
0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \ |
0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \ |
0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \ |
0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \ |
0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \ |
0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \ |
0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \ |
0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \ |
0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \ |
0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \ |
0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \ |
0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \ |
0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \ |
0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \ |
0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \ |
0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \ |
0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \ |
0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \ |
0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \ |
0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \ |
0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \ |
0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97 \ |
} |
/* END FILE */ |
/* This is taken from tests/data_files/cli-rsa.key. */ |
/* BEGIN FILE string macro TEST_CLI_KEY_RSA_PEM tests/data_files/cli-rsa.key */ |
#define TEST_CLI_KEY_RSA_PEM \ |
"-----BEGIN RSA PRIVATE KEY-----\r\n" \ |
"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" \ |
"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" \ |
"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" \ |
"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" \ |
"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" \ |
"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" \ |
"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" \ |
"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" \ |
"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" \ |
"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" \ |
"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" \ |
"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" \ |
"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" \ |
"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" \ |
"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" \ |
"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" \ |
"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" \ |
"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" \ |
"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" \ |
"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" \ |
"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" \ |
"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" \ |
"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" \ |
"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" \ |
"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" \ |
"-----END RSA PRIVATE KEY-----\r\n"/* END FILE */ |
/* This was generated from tests/data_files/cli-rsa.key.der using `xxd -i`. */ |
/* BEGIN FILE binary macro TEST_CLI_KEY_RSA_DER tests/data_files/cli-rsa.key.der */ |
#define TEST_CLI_KEY_RSA_DER { \ |
0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ |
0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, 0x45, 0xd9, 0x14, \ |
0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, 0x33, 0xad, 0x0d, \ |
0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, 0xcc, 0x66, 0x85, \ |
0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, 0x9e, 0x0a, 0x6e, \ |
0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, 0x93, 0x86, 0x49, \ |
0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, 0xd4, 0x2f, 0x77, \ |
0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, 0x48, 0x70, 0xf5, \ |
0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, 0xe6, 0x43, 0xea, \ |
0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, 0x57, 0x4e, 0xa9, \ |
0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, 0x32, 0x30, 0xd5, \ |
0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, 0x5f, 0xf9, 0x3d, \ |
0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, 0xfb, 0xe5, 0x0c, \ |
0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, 0x7f, 0xca, 0xad, \ |
0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, 0xe0, 0x9b, 0xf8, \ |
0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, 0x04, 0x66, 0xc7, \ |
0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, 0x06, 0x67, 0xf4, \ |
0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, 0x3c, 0x8b, 0x35, \ |
0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, 0xfc, 0x36, 0x6b, \ |
0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, 0x00, 0xcf, 0xaf, \ |
0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, 0xe7, 0x50, 0x71, \ |
0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, 0xe4, 0xc4, 0xfd, \ |
0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ |
0x00, 0x67, 0x4d, 0xb5, 0xf6, 0x03, 0x89, 0xaa, 0x7a, 0x6f, 0x3b, 0x2d, \ |
0xca, 0x10, 0xa2, 0x23, 0xc9, 0xbd, 0x4e, 0xda, 0xe1, 0x67, 0x0e, 0x0c, \ |
0x8a, 0xc6, 0x84, 0x68, 0xdf, 0xe5, 0x97, 0x75, 0xd2, 0x8d, 0xa3, 0x86, \ |
0xd9, 0xdb, 0xd5, 0xeb, 0x13, 0x19, 0x08, 0xc5, 0x7e, 0xe5, 0x37, 0x97, \ |
0x0c, 0x73, 0x80, 0x66, 0x76, 0x35, 0xf1, 0x88, 0xb5, 0xf2, 0xfc, 0xf3, \ |
0xe1, 0x4b, 0x76, 0x4e, 0x73, 0x45, 0xce, 0x2c, 0xc2, 0x10, 0x26, 0x0d, \ |
0x68, 0x0d, 0x9f, 0x49, 0x3d, 0xd6, 0x80, 0x89, 0xe7, 0xc5, 0x49, 0x15, \ |
0xdd, 0x85, 0xc0, 0xc8, 0xfe, 0x82, 0x37, 0x12, 0x5a, 0x0a, 0x6b, 0xf6, \ |
0x68, 0x0d, 0x32, 0x16, 0xbd, 0xa4, 0x15, 0x54, 0x9e, 0x68, 0xa1, 0xad, \ |
0xca, 0x6b, 0xe5, 0x8c, 0xda, 0x76, 0x35, 0x59, 0x2f, 0x9b, 0xb4, 0xe1, \ |
0xf1, 0xf0, 0x50, 0x04, 0xee, 0xc8, 0xec, 0x05, 0xe1, 0xcf, 0x8d, 0xe4, \ |
0xd2, 0x64, 0x7b, 0x5e, 0x63, 0xe0, 0x7b, 0x07, 0xbc, 0x02, 0x96, 0x4e, \ |
0x1b, 0x78, 0x6c, 0xb6, 0x43, 0x9a, 0x32, 0xf6, 0xd6, 0x02, 0xf5, 0x80, \ |
0xcc, 0x26, 0x6e, 0xa5, 0xd0, 0xe3, 0x65, 0x88, 0xce, 0x26, 0xa9, 0x40, \ |
0xe1, 0xe1, 0x00, 0xe0, 0x7f, 0x3f, 0xc3, 0xb1, 0x7c, 0xde, 0xbe, 0x42, \ |
0xba, 0x07, 0x81, 0x13, 0xc2, 0xe0, 0x11, 0x11, 0x23, 0x2c, 0xf8, 0xb2, \ |
0x7a, 0x3a, 0xd4, 0xe4, 0x7d, 0x5f, 0xb9, 0xb1, 0x18, 0xfa, 0x1d, 0x1d, \ |
0x97, 0x91, 0xd9, 0x04, 0x9e, 0xbc, 0xc9, 0xb4, 0xd7, 0x7d, 0x0e, 0x54, \ |
0xf6, 0x8f, 0xd0, 0x28, 0x0d, 0xdd, 0x77, 0x4b, 0x68, 0x04, 0x48, 0x61, \ |
0x75, 0x15, 0x03, 0x1b, 0x35, 0xad, 0x8e, 0xfc, 0x24, 0x11, 0x07, 0xea, \ |
0x17, 0x5a, 0xde, 0x19, 0x68, 0xff, 0xb6, 0x87, 0x7f, 0x80, 0x2a, 0x5f, \ |
0x0c, 0x58, 0xba, 0x5f, 0x41, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x03, 0xaf, \ |
0xfe, 0x98, 0xd2, 0x0b, 0x7b, 0x72, 0xe9, 0x3b, 0x8e, 0xbc, 0xa5, 0xf6, \ |
0xac, 0xe5, 0x22, 0x06, 0xb2, 0xd7, 0x5e, 0xfd, 0x89, 0x4b, 0x16, 0x67, \ |
0x32, 0x83, 0x22, 0x58, 0x8e, 0x62, 0xa4, 0xb4, 0x2d, 0xf9, 0x16, 0x13, \ |
0x54, 0xf6, 0x9f, 0x2f, 0xf9, 0xbb, 0x0e, 0x7e, 0x8c, 0x6f, 0x08, 0xda, \ |
0xc8, 0xe9, 0x1c, 0x66, 0x10, 0x70, 0x93, 0x90, 0x8d, 0xcf, 0x90, 0x3a, \ |
0x43, 0x89, 0x49, 0xeb, 0x83, 0x2a, 0xfe, 0x5a, 0x87, 0xce, 0x74, 0x42, \ |
0x41, 0x0d, 0x8c, 0x73, 0x51, 0xbc, 0x7b, 0x20, 0xc5, 0xfd, 0xf6, 0x0b, \ |
0x65, 0xed, 0xa9, 0x2e, 0xfc, 0x0f, 0xf5, 0x50, 0xf9, 0x8d, 0x37, 0x36, \ |
0x9a, 0x20, 0xdf, 0xc3, 0xe3, 0x27, 0xbc, 0x98, 0x72, 0xc1, 0x14, 0x4b, \ |
0x71, 0xe9, 0x83, 0x14, 0xff, 0x24, 0xe2, 0x14, 0x15, 0xb6, 0x6f, 0x0f, \ |
0x32, 0x9d, 0xd9, 0x98, 0xd1, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x0c, 0xfb, \ |
0xc3, 0x33, 0x9b, 0x47, 0x88, 0x27, 0xf2, 0x26, 0xde, 0xeb, 0x5e, 0xee, \ |
0x40, 0xf6, 0x63, 0x5b, 0x35, 0x23, 0xf5, 0xd5, 0x07, 0x61, 0xdf, 0xa2, \ |
0x9f, 0x58, 0x30, 0x04, 0x22, 0x2b, 0xb4, 0xd9, 0xda, 0x46, 0x7f, 0x48, \ |
0xf5, 0x4f, 0xd0, 0xea, 0xd7, 0xa0, 0x45, 0x8a, 0x62, 0x8b, 0x8c, 0xac, \ |
0x73, 0x5e, 0xfa, 0x36, 0x65, 0x3e, 0xba, 0x6c, 0xba, 0x5e, 0x6b, 0x92, \ |
0x29, 0x5e, 0x6a, 0x0f, 0xd6, 0xd2, 0xa5, 0x95, 0x86, 0xda, 0x72, 0xc5, \ |
0x9e, 0xc9, 0x6b, 0x37, 0x5e, 0x4b, 0x9b, 0x77, 0xe1, 0x67, 0x1a, 0x1e, \ |
0x30, 0xd8, 0x41, 0x68, 0x40, 0xd3, 0x9c, 0xb4, 0xf6, 0xeb, 0x2a, 0x22, \ |
0xdf, 0x78, 0x29, 0xd2, 0x64, 0x92, 0x5b, 0x2f, 0x78, 0x64, 0x4a, 0xa2, \ |
0xa6, 0x6b, 0x3e, 0x50, 0xb1, 0x7a, 0xb1, 0x8d, 0x59, 0xb4, 0x55, 0xba, \ |
0xb6, 0x91, 0x85, 0xa3, 0x2f, 0x02, 0x81, 0x80, 0x10, 0x1e, 0x19, 0xe7, \ |
0xbc, 0x97, 0xe5, 0x22, 0xcd, 0xa4, 0xcb, 0x8a, 0xb5, 0xd0, 0x1e, 0xb4, \ |
0x65, 0xcc, 0x45, 0xa7, 0x7a, 0xed, 0x0e, 0x99, 0x29, 0xd0, 0x9c, 0x61, \ |
0x14, 0xb8, 0x62, 0x8b, 0x31, 0x6b, 0xba, 0x33, 0x2d, 0x65, 0x28, 0xd8, \ |
0x36, 0x6e, 0x54, 0xec, 0xa9, 0x20, 0x3d, 0x51, 0xe1, 0x2c, 0x42, 0xc4, \ |
0x52, 0xf0, 0xa6, 0x3a, 0x72, 0x93, 0xb7, 0x86, 0xa9, 0xfe, 0xf6, 0x74, \ |
0x07, 0x12, 0x4d, 0x7b, 0x51, 0x99, 0x1f, 0x7a, 0x56, 0xe9, 0x20, 0x2f, \ |
0x18, 0x34, 0x29, 0x97, 0xdb, 0x06, 0xee, 0xeb, 0xbf, 0xbd, 0x31, 0x4f, \ |
0xfa, 0x50, 0xb1, 0xba, 0x49, 0xb3, 0xc4, 0x1d, 0x03, 0xae, 0xb0, 0xdc, \ |
0xbe, 0x8a, 0xc4, 0x90, 0xa3, 0x28, 0x9b, 0xb6, 0x42, 0x09, 0x1b, 0xd6, \ |
0x29, 0x9b, 0x19, 0xe9, 0x87, 0x87, 0xd9, 0x9f, 0x35, 0x05, 0xab, 0x91, \ |
0x8f, 0x6d, 0x7c, 0x91, 0x02, 0x81, 0x81, 0x00, 0x94, 0x57, 0xf0, 0xe0, \ |
0x28, 0xfd, 0xbd, 0xf3, 0x9c, 0x43, 0x4d, 0x3e, 0xfd, 0x37, 0x4f, 0x23, \ |
0x52, 0x8d, 0xe1, 0x4c, 0xfe, 0x4c, 0x55, 0x80, 0x82, 0xba, 0x3f, 0xfe, \ |
0x51, 0xe1, 0x30, 0xd5, 0x3b, 0xd9, 0x73, 0x1d, 0xcb, 0x25, 0xbc, 0xbb, \ |
0x3f, 0xa5, 0xda, 0x77, 0xa6, 0xb5, 0xfc, 0x1a, 0xaf, 0x79, 0xa1, 0xb2, \ |
0x14, 0xa2, 0x1f, 0x10, 0x52, 0x1a, 0x05, 0x40, 0x48, 0xb6, 0x4f, 0x34, \ |
0xd6, 0xc0, 0xc3, 0xa4, 0x36, 0x98, 0x73, 0x88, 0x0b, 0xd3, 0x45, 0xdc, \ |
0xee, 0x51, 0x6e, 0x04, 0x73, 0x99, 0x93, 0x12, 0x58, 0x96, 0xcb, 0x39, \ |
0x42, 0xb1, 0xa9, 0xb8, 0xe1, 0x25, 0xf5, 0x9c, 0x14, 0xb7, 0x92, 0x2b, \ |
0x14, 0xb0, 0x5d, 0x61, 0xa2, 0xaa, 0x34, 0x7c, 0xcd, 0x54, 0x2d, 0x69, \ |
0x08, 0xf7, 0xdb, 0xfc, 0x9c, 0x87, 0xe8, 0x3a, 0xf6, 0x1d, 0x4c, 0x6a, \ |
0x83, 0x15, 0x30, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9c, 0x53, 0xa1, 0xb6, \ |
0x2f, 0xc0, 0x06, 0xf5, 0xdf, 0x5c, 0xd1, 0x4a, 0x4e, 0xc8, 0xbd, 0x6d, \ |
0x32, 0xf1, 0x5e, 0xe5, 0x3b, 0x70, 0xd0, 0xa8, 0xe5, 0x41, 0x57, 0x6c, \ |
0x87, 0x53, 0x0f, 0xeb, 0x28, 0xa0, 0x62, 0x8f, 0x43, 0x62, 0xec, 0x2e, \ |
0x6c, 0x71, 0x55, 0x5b, 0x6a, 0xf4, 0x74, 0x14, 0xea, 0x7a, 0x03, 0xf6, \ |
0xfc, 0xa4, 0xce, 0xc4, 0xac, 0xda, 0x1d, 0xf0, 0xb5, 0xa9, 0xfd, 0x11, \ |
0x18, 0x3b, 0x14, 0xa0, 0x90, 0x8d, 0x26, 0xb7, 0x75, 0x73, 0x0a, 0x02, \ |
0x2c, 0x6f, 0x0f, 0xd8, 0x41, 0x78, 0xc3, 0x73, 0x81, 0xac, 0xaa, 0xaf, \ |
0xf2, 0xee, 0x32, 0xb5, 0x8d, 0x05, 0xf9, 0x59, 0x5a, 0x9e, 0x3e, 0x65, \ |
0x9b, 0x74, 0xda, 0xa0, 0x74, 0x95, 0x17, 0x5f, 0x8d, 0x58, 0xfc, 0x8e, \ |
0x4e, 0x2c, 0x1e, 0xbc, 0x81, 0x02, 0x18, 0xac, 0x12, 0xc6, 0xf9, 0x64, \ |
0x8b, 0x87, 0xc3, 0x00 \ |
} |
/* END FILE */ |
/* |
* |
* Test certificates and keys as C variables |
* |
*/ |
/* |
* CA |
*/ |
const char mbedtls_test_ca_crt_ec_pem[] = TEST_CA_CRT_EC_PEM; |
const char mbedtls_test_ca_key_ec_pem[] = TEST_CA_KEY_EC_PEM; |
const char mbedtls_test_ca_pwd_ec_pem[] = TEST_CA_PWD_EC_PEM; |
const char mbedtls_test_ca_key_rsa_pem[] = TEST_CA_KEY_RSA_PEM; |
const char mbedtls_test_ca_pwd_rsa_pem[] = TEST_CA_PWD_RSA_PEM; |
const char mbedtls_test_ca_crt_rsa_sha1_pem[] = TEST_CA_CRT_RSA_SHA1_PEM; |
const char mbedtls_test_ca_crt_rsa_sha256_pem[] = TEST_CA_CRT_RSA_SHA256_PEM; |
const unsigned char mbedtls_test_ca_crt_ec_der[] = TEST_CA_CRT_EC_DER; |
const unsigned char mbedtls_test_ca_key_ec_der[] = TEST_CA_KEY_EC_DER; |
const unsigned char mbedtls_test_ca_key_rsa_der[] = TEST_CA_KEY_RSA_DER; |
const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[] = |
TEST_CA_CRT_RSA_SHA1_DER; |
const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[] = |
TEST_CA_CRT_RSA_SHA256_DER; |
const size_t mbedtls_test_ca_crt_ec_pem_len = |
sizeof( mbedtls_test_ca_crt_ec_pem ); |
const size_t mbedtls_test_ca_key_ec_pem_len = |
sizeof( mbedtls_test_ca_key_ec_pem ); |
const size_t mbedtls_test_ca_pwd_ec_pem_len = |
sizeof( mbedtls_test_ca_pwd_ec_pem ) - 1; |
const size_t mbedtls_test_ca_key_rsa_pem_len = |
sizeof( mbedtls_test_ca_key_rsa_pem ); |
const size_t mbedtls_test_ca_pwd_rsa_pem_len = |
sizeof( mbedtls_test_ca_pwd_rsa_pem ) - 1; |
const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len = |
sizeof( mbedtls_test_ca_crt_rsa_sha1_pem ); |
const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len = |
sizeof( mbedtls_test_ca_crt_rsa_sha256_pem ); |
const size_t mbedtls_test_ca_crt_ec_der_len = |
sizeof( mbedtls_test_ca_crt_ec_der ); |
const size_t mbedtls_test_ca_key_ec_der_len = |
sizeof( mbedtls_test_ca_key_ec_der ); |
const size_t mbedtls_test_ca_pwd_ec_der_len = 0; |
const size_t mbedtls_test_ca_key_rsa_der_len = |
sizeof( mbedtls_test_ca_key_rsa_der ); |
const size_t mbedtls_test_ca_pwd_rsa_der_len = 0; |
const size_t mbedtls_test_ca_crt_rsa_sha1_der_len = |
sizeof( mbedtls_test_ca_crt_rsa_sha1_der ); |
const size_t mbedtls_test_ca_crt_rsa_sha256_der_len = |
sizeof( mbedtls_test_ca_crt_rsa_sha256_der ); |
/* |
* Server |
*/ |
const char mbedtls_test_srv_crt_ec_pem[] = TEST_SRV_CRT_EC_PEM; |
const char mbedtls_test_srv_key_ec_pem[] = TEST_SRV_KEY_EC_PEM; |
const char mbedtls_test_srv_pwd_ec_pem[] = ""; |
const char mbedtls_test_srv_key_rsa_pem[] = TEST_SRV_KEY_RSA_PEM; |
const char mbedtls_test_srv_pwd_rsa_pem[] = ""; |
const char mbedtls_test_srv_crt_rsa_sha1_pem[] = TEST_SRV_CRT_RSA_SHA1_PEM; |
const char mbedtls_test_srv_crt_rsa_sha256_pem[] = TEST_SRV_CRT_RSA_SHA256_PEM; |
const unsigned char mbedtls_test_srv_crt_ec_der[] = TEST_SRV_CRT_EC_DER; |
const unsigned char mbedtls_test_srv_key_ec_der[] = TEST_SRV_KEY_EC_DER; |
const unsigned char mbedtls_test_srv_key_rsa_der[] = TEST_SRV_KEY_RSA_DER; |
const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[] = |
TEST_SRV_CRT_RSA_SHA1_DER; |
const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[] = |
TEST_SRV_CRT_RSA_SHA256_DER; |
const size_t mbedtls_test_srv_crt_ec_pem_len = |
sizeof( mbedtls_test_srv_crt_ec_pem ); |
const size_t mbedtls_test_srv_key_ec_pem_len = |
sizeof( mbedtls_test_srv_key_ec_pem ); |
const size_t mbedtls_test_srv_pwd_ec_pem_len = |
sizeof( mbedtls_test_srv_pwd_ec_pem ) - 1; |
const size_t mbedtls_test_srv_key_rsa_pem_len = |
sizeof( mbedtls_test_srv_key_rsa_pem ); |
const size_t mbedtls_test_srv_pwd_rsa_pem_len = |
sizeof( mbedtls_test_srv_pwd_rsa_pem ) - 1; |
const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len = |
sizeof( mbedtls_test_srv_crt_rsa_sha1_pem ); |
const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len = |
sizeof( mbedtls_test_srv_crt_rsa_sha256_pem ); |
const size_t mbedtls_test_srv_crt_ec_der_len = |
sizeof( mbedtls_test_srv_crt_ec_der ); |
const size_t mbedtls_test_srv_key_ec_der_len = |
sizeof( mbedtls_test_srv_key_ec_der ); |
const size_t mbedtls_test_srv_pwd_ec_der_len = 0; |
const size_t mbedtls_test_srv_key_rsa_der_len = |
sizeof( mbedtls_test_srv_key_rsa_der ); |
const size_t mbedtls_test_srv_pwd_rsa_der_len = 0; |
const size_t mbedtls_test_srv_crt_rsa_sha1_der_len = |
sizeof( mbedtls_test_srv_crt_rsa_sha1_der ); |
const size_t mbedtls_test_srv_crt_rsa_sha256_der_len = |
sizeof( mbedtls_test_srv_crt_rsa_sha256_der ); |
/* |
* Client |
*/ |
const char mbedtls_test_cli_crt_ec_pem[] = TEST_CLI_CRT_EC_PEM; |
const char mbedtls_test_cli_key_ec_pem[] = TEST_CLI_KEY_EC_PEM; |
const char mbedtls_test_cli_pwd_ec_pem[] = ""; |
const char mbedtls_test_cli_key_rsa_pem[] = TEST_CLI_KEY_RSA_PEM; |
const char mbedtls_test_cli_pwd_rsa_pem[] = ""; |
const char mbedtls_test_cli_crt_rsa_pem[] = TEST_CLI_CRT_RSA_PEM; |
const unsigned char mbedtls_test_cli_crt_ec_der[] = TEST_CLI_CRT_EC_DER; |
const unsigned char mbedtls_test_cli_key_ec_der[] = TEST_CLI_KEY_EC_DER; |
const unsigned char mbedtls_test_cli_key_rsa_der[] = TEST_CLI_KEY_RSA_DER; |
const unsigned char mbedtls_test_cli_crt_rsa_der[] = TEST_CLI_CRT_RSA_DER; |
const size_t mbedtls_test_cli_crt_ec_pem_len = |
sizeof( mbedtls_test_cli_crt_ec_pem ); |
const size_t mbedtls_test_cli_key_ec_pem_len = |
sizeof( mbedtls_test_cli_key_ec_pem ); |
const size_t mbedtls_test_cli_pwd_ec_pem_len = |
sizeof( mbedtls_test_cli_pwd_ec_pem ) - 1; |
const size_t mbedtls_test_cli_key_rsa_pem_len = |
sizeof( mbedtls_test_cli_key_rsa_pem ); |
const size_t mbedtls_test_cli_pwd_rsa_pem_len = |
sizeof( mbedtls_test_cli_pwd_rsa_pem ) - 1; |
const size_t mbedtls_test_cli_crt_rsa_pem_len = |
sizeof( mbedtls_test_cli_crt_rsa_pem ); |
const size_t mbedtls_test_cli_crt_ec_der_len = |
sizeof( mbedtls_test_cli_crt_ec_der ); |
const size_t mbedtls_test_cli_key_ec_der_len = |
sizeof( mbedtls_test_cli_key_ec_der ); |
const size_t mbedtls_test_cli_key_rsa_der_len = |
sizeof( mbedtls_test_cli_key_rsa_der ); |
const size_t mbedtls_test_cli_crt_rsa_der_len = |
sizeof( mbedtls_test_cli_crt_rsa_der ); |
/* |
* |
* Definitions of test CRTs without specification of all parameters, choosing |
* them automatically according to the config. For example, mbedtls_test_ca_crt |
* is one of mbedtls_test_ca_crt_{rsa|ec}_{sha1|sha256}_{pem|der}. |
* |
*/ |
/* |
* Dispatch between PEM and DER according to config |
*/ |
#if defined(MBEDTLS_PEM_PARSE_C) |
/* PEM encoded test CA certificates and keys */ |
#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_PEM |
#define TEST_CA_PWD_RSA TEST_CA_PWD_RSA_PEM |
#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_PEM |
#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_PEM |
#define TEST_CA_KEY_EC TEST_CA_KEY_EC_PEM |
#define TEST_CA_PWD_EC TEST_CA_PWD_EC_PEM |
#define TEST_CA_CRT_EC TEST_CA_CRT_EC_PEM |
/* PEM encoded test server certificates and keys */ |
#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_PEM |
#define TEST_SRV_PWD_RSA "" |
#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_PEM |
#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_PEM |
#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_PEM |
#define TEST_SRV_PWD_EC "" |
#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_PEM |
/* PEM encoded test client certificates and keys */ |
#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_PEM |
#define TEST_CLI_PWD_RSA "" |
#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_PEM |
#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_PEM |
#define TEST_CLI_PWD_EC "" |
#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_PEM |
#else /* MBEDTLS_PEM_PARSE_C */ |
/* DER encoded test CA certificates and keys */ |
#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_DER |
#define TEST_CA_PWD_RSA "" |
#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_DER |
#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_DER |
#define TEST_CA_KEY_EC TEST_CA_KEY_EC_DER |
#define TEST_CA_PWD_EC "" |
#define TEST_CA_CRT_EC TEST_CA_CRT_EC_DER |
/* DER encoded test server certificates and keys */ |
#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_DER |
#define TEST_SRV_PWD_RSA "" |
#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_DER |
#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_DER |
#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_DER |
#define TEST_SRV_PWD_EC "" |
#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_DER |
/* DER encoded test client certificates and keys */ |
#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_DER |
#define TEST_CLI_PWD_RSA "" |
#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_DER |
#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_DER |
#define TEST_CLI_PWD_EC "" |
#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_DER |
#endif /* MBEDTLS_PEM_PARSE_C */ |
const char mbedtls_test_ca_key_rsa[] = TEST_CA_KEY_RSA; |
const char mbedtls_test_ca_pwd_rsa[] = TEST_CA_PWD_RSA; |
const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; |
const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; |
const char mbedtls_test_ca_key_ec[] = TEST_CA_KEY_EC; |
const char mbedtls_test_ca_pwd_ec[] = TEST_CA_PWD_EC; |
const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; |
const char mbedtls_test_srv_key_rsa[] = TEST_SRV_KEY_RSA; |
const char mbedtls_test_srv_pwd_rsa[] = TEST_SRV_PWD_RSA; |
const char mbedtls_test_srv_crt_rsa_sha256[] = TEST_SRV_CRT_RSA_SHA256; |
const char mbedtls_test_srv_crt_rsa_sha1[] = TEST_SRV_CRT_RSA_SHA1; |
const char mbedtls_test_srv_key_ec[] = TEST_SRV_KEY_EC; |
const char mbedtls_test_srv_pwd_ec[] = TEST_SRV_PWD_EC; |
const char mbedtls_test_srv_crt_ec[] = TEST_SRV_CRT_EC; |
const char mbedtls_test_cli_key_rsa[] = TEST_CLI_KEY_RSA; |
const char mbedtls_test_cli_pwd_rsa[] = TEST_CLI_PWD_RSA; |
const char mbedtls_test_cli_crt_rsa[] = TEST_CLI_CRT_RSA; |
const char mbedtls_test_cli_key_ec[] = TEST_CLI_KEY_EC; |
const char mbedtls_test_cli_pwd_ec[] = TEST_CLI_PWD_EC; |
const char mbedtls_test_cli_crt_ec[] = TEST_CLI_CRT_EC; |
const size_t mbedtls_test_ca_key_rsa_len = |
sizeof( mbedtls_test_ca_key_rsa ); |
const size_t mbedtls_test_ca_pwd_rsa_len = |
sizeof( mbedtls_test_ca_pwd_rsa ) - 1; |
const size_t mbedtls_test_ca_crt_rsa_sha256_len = |
sizeof( mbedtls_test_ca_crt_rsa_sha256 ); |
const size_t mbedtls_test_ca_crt_rsa_sha1_len = |
sizeof( mbedtls_test_ca_crt_rsa_sha1 ); |
const size_t mbedtls_test_ca_key_ec_len = |
sizeof( mbedtls_test_ca_key_ec ); |
const size_t mbedtls_test_ca_pwd_ec_len = |
sizeof( mbedtls_test_ca_pwd_ec ) - 1; |
const size_t mbedtls_test_ca_crt_ec_len = |
sizeof( mbedtls_test_ca_crt_ec ); |
const size_t mbedtls_test_srv_key_rsa_len = |
sizeof( mbedtls_test_srv_key_rsa ); |
const size_t mbedtls_test_srv_pwd_rsa_len = |
sizeof( mbedtls_test_srv_pwd_rsa ) -1; |
const size_t mbedtls_test_srv_crt_rsa_sha256_len = |
sizeof( mbedtls_test_srv_crt_rsa_sha256 ); |
const size_t mbedtls_test_srv_crt_rsa_sha1_len = |
sizeof( mbedtls_test_srv_crt_rsa_sha1 ); |
const size_t mbedtls_test_srv_key_ec_len = |
sizeof( mbedtls_test_srv_key_ec ); |
const size_t mbedtls_test_srv_pwd_ec_len = |
sizeof( mbedtls_test_srv_pwd_ec ) - 1; |
const size_t mbedtls_test_srv_crt_ec_len = |
sizeof( mbedtls_test_srv_crt_ec ); |
const size_t mbedtls_test_cli_key_rsa_len = |
sizeof( mbedtls_test_cli_key_rsa ); |
const size_t mbedtls_test_cli_pwd_rsa_len = |
sizeof( mbedtls_test_cli_pwd_rsa ) - 1; |
const size_t mbedtls_test_cli_crt_rsa_len = |
sizeof( mbedtls_test_cli_crt_rsa ); |
const size_t mbedtls_test_cli_key_ec_len = |
sizeof( mbedtls_test_cli_key_ec ); |
const size_t mbedtls_test_cli_pwd_ec_len = |
sizeof( mbedtls_test_cli_pwd_ec ) - 1; |
const size_t mbedtls_test_cli_crt_ec_len = |
sizeof( mbedtls_test_cli_crt_ec ); |
/* |
* Dispatch between SHA-1 and SHA-256 |
*/ |
#if defined(MBEDTLS_SHA256_C) |
#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA256 |
#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA256 |
#else |
#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA1 |
#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA1 |
#endif /* MBEDTLS_SHA256_C */ |
const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; |
const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA; |
const size_t mbedtls_test_ca_crt_rsa_len = |
sizeof( mbedtls_test_ca_crt_rsa ); |
const size_t mbedtls_test_srv_crt_rsa_len = |
sizeof( mbedtls_test_srv_crt_rsa ); |
/* |
* Dispatch between RSA and EC |
*/ |
#if defined(MBEDTLS_RSA_C) |
#define TEST_CA_KEY TEST_CA_KEY_RSA |
#define TEST_CA_PWD TEST_CA_PWD_RSA |
#define TEST_CA_CRT TEST_CA_CRT_RSA |
#define TEST_SRV_KEY TEST_SRV_KEY_RSA |
#define TEST_SRV_PWD TEST_SRV_PWD_RSA |
#define TEST_SRV_CRT TEST_SRV_CRT_RSA |
#define TEST_CLI_KEY TEST_CLI_KEY_RSA |
#define TEST_CLI_PWD TEST_CLI_PWD_RSA |
#define TEST_CLI_CRT TEST_CLI_CRT_RSA |
#else /* no RSA, so assume ECDSA */ |
#define TEST_CA_KEY TEST_CA_KEY_EC |
#define TEST_CA_PWD TEST_CA_PWD_EC |
#define TEST_CA_CRT TEST_CA_CRT_EC |
#define TEST_SRV_KEY TEST_SRV_KEY_EC |
#define TEST_SRV_PWD TEST_SRV_PWD_EC |
#define TEST_SRV_CRT TEST_SRV_CRT_EC |
#define TEST_CLI_KEY TEST_CLI_KEY_EC |
#define TEST_CLI_PWD TEST_CLI_PWD_EC |
#define TEST_CLI_CRT TEST_CLI_CRT_EC |
#endif /* MBEDTLS_RSA_C */ |
/* API stability forces us to declare |
* mbedtls_test_{ca|srv|cli}_{key|pwd|crt} |
* as pointers. */ |
static const char test_ca_key[] = TEST_CA_KEY; |
static const char test_ca_pwd[] = TEST_CA_PWD; |
static const char test_ca_crt[] = TEST_CA_CRT; |
static const char test_srv_key[] = TEST_SRV_KEY; |
static const char test_srv_pwd[] = TEST_SRV_PWD; |
static const char test_srv_crt[] = TEST_SRV_CRT; |
static const char test_cli_key[] = TEST_CLI_KEY; |
static const char test_cli_pwd[] = TEST_CLI_PWD; |
static const char test_cli_crt[] = TEST_CLI_CRT; |
const char *mbedtls_test_ca_key = test_ca_key; |
const char *mbedtls_test_ca_pwd = test_ca_pwd; |
const char *mbedtls_test_ca_crt = test_ca_crt; |
const char *mbedtls_test_srv_key = test_srv_key; |
const char *mbedtls_test_srv_pwd = test_srv_pwd; |
const char *mbedtls_test_srv_crt = test_srv_crt; |
const char *mbedtls_test_cli_key = test_cli_key; |
const char *mbedtls_test_cli_pwd = test_cli_pwd; |
const char *mbedtls_test_cli_crt = test_cli_crt; |
const size_t mbedtls_test_ca_key_len = |
sizeof( test_ca_key ); |
const size_t mbedtls_test_ca_pwd_len = |
sizeof( test_ca_pwd ) - 1; |
const size_t mbedtls_test_ca_crt_len = |
sizeof( test_ca_crt ); |
const size_t mbedtls_test_srv_key_len = |
sizeof( test_srv_key ); |
const size_t mbedtls_test_srv_pwd_len = |
sizeof( test_srv_pwd ) - 1; |
const size_t mbedtls_test_srv_crt_len = |
sizeof( test_srv_crt ); |
const size_t mbedtls_test_cli_key_len = |
sizeof( test_cli_key ); |
const size_t mbedtls_test_cli_pwd_len = |
sizeof( test_cli_pwd ) - 1; |
const size_t mbedtls_test_cli_crt_len = |
sizeof( test_cli_crt ); |
/* |
* |
* Lists of certificates |
* |
*/ |
/* List of CAs in PEM or DER, depending on config */ |
const char * mbedtls_test_cas[] = { |
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) |
mbedtls_test_ca_crt_rsa_sha1, |
#endif |
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) |
mbedtls_test_ca_crt_rsa_sha256, |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
mbedtls_test_ca_crt_ec, |
#endif |
NULL |
}; |
const size_t mbedtls_test_cas_len[] = { |
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) |
sizeof( mbedtls_test_ca_crt_rsa_sha1 ), |
#endif |
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) |
sizeof( mbedtls_test_ca_crt_rsa_sha256 ), |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
sizeof( mbedtls_test_ca_crt_ec ), |
#endif |
0 |
}; |
/* List of all available CA certificates in DER format */ |
const unsigned char * mbedtls_test_cas_der[] = { |
#if defined(MBEDTLS_RSA_C) |
#if defined(MBEDTLS_SHA256_C) |
mbedtls_test_ca_crt_rsa_sha256_der, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA1_C) |
mbedtls_test_ca_crt_rsa_sha1_der, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECDSA_C) |
mbedtls_test_ca_crt_ec_der, |
#endif /* MBEDTLS_ECDSA_C */ |
NULL |
}; |
const size_t mbedtls_test_cas_der_len[] = { |
#if defined(MBEDTLS_RSA_C) |
#if defined(MBEDTLS_SHA256_C) |
sizeof( mbedtls_test_ca_crt_rsa_sha256_der ), |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA1_C) |
sizeof( mbedtls_test_ca_crt_rsa_sha1_der ), |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECDSA_C) |
sizeof( mbedtls_test_ca_crt_ec_der ), |
#endif /* MBEDTLS_ECDSA_C */ |
0 |
}; |
/* Concatenation of all available CA certificates in PEM format */ |
#if defined(MBEDTLS_PEM_PARSE_C) |
const char mbedtls_test_cas_pem[] = |
#if defined(MBEDTLS_RSA_C) |
#if defined(MBEDTLS_SHA256_C) |
TEST_CA_CRT_RSA_SHA256_PEM |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA1_C) |
TEST_CA_CRT_RSA_SHA1_PEM |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECDSA_C) |
TEST_CA_CRT_EC_PEM |
#endif /* MBEDTLS_ECDSA_C */ |
""; |
const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); |
#endif /* MBEDTLS_PEM_PARSE_C */ |
#endif /* MBEDTLS_CERTS_C */ |
/programs/develop/libraries/kos_mbedtls/library/chacha20.c |
---|
0,0 → 1,572 |
/** |
* \file chacha20.c |
* |
* \brief ChaCha20 cipher. |
* |
* \author Daniel King <damaki.gh@gmail.com> |
* |
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CHACHA20_C) |
#include "mbedtls/chacha20.h" |
#include "mbedtls/platform_util.h" |
#include <stddef.h> |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_CHACHA20_ALT) |
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ |
!defined(inline) && !defined(__cplusplus) |
#define inline __inline |
#endif |
/* Parameter validation macros */ |
#define CHACHA20_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) |
#define CHACHA20_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#define BYTES_TO_U32_LE( data, offset ) \ |
( (uint32_t) (data)[offset] \ |
| (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \ |
| (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \ |
| (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \ |
) |
#define ROTL32( value, amount ) \ |
( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) ) |
#define CHACHA20_CTR_INDEX ( 12U ) |
#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) |
/** |
* \brief ChaCha20 quarter round operation. |
* |
* The quarter round is defined as follows (from RFC 7539): |
* 1. a += b; d ^= a; d <<<= 16; |
* 2. c += d; b ^= c; b <<<= 12; |
* 3. a += b; d ^= a; d <<<= 8; |
* 4. c += d; b ^= c; b <<<= 7; |
* |
* \param state ChaCha20 state to modify. |
* \param a The index of 'a' in the state. |
* \param b The index of 'b' in the state. |
* \param c The index of 'c' in the state. |
* \param d The index of 'd' in the state. |
*/ |
static inline void chacha20_quarter_round( uint32_t state[16], |
size_t a, |
size_t b, |
size_t c, |
size_t d ) |
{ |
/* a += b; d ^= a; d <<<= 16; */ |
state[a] += state[b]; |
state[d] ^= state[a]; |
state[d] = ROTL32( state[d], 16 ); |
/* c += d; b ^= c; b <<<= 12 */ |
state[c] += state[d]; |
state[b] ^= state[c]; |
state[b] = ROTL32( state[b], 12 ); |
/* a += b; d ^= a; d <<<= 8; */ |
state[a] += state[b]; |
state[d] ^= state[a]; |
state[d] = ROTL32( state[d], 8 ); |
/* c += d; b ^= c; b <<<= 7; */ |
state[c] += state[d]; |
state[b] ^= state[c]; |
state[b] = ROTL32( state[b], 7 ); |
} |
/** |
* \brief Perform the ChaCha20 inner block operation. |
* |
* This function performs two rounds: the column round and the |
* diagonal round. |
* |
* \param state The ChaCha20 state to update. |
*/ |
static void chacha20_inner_block( uint32_t state[16] ) |
{ |
chacha20_quarter_round( state, 0, 4, 8, 12 ); |
chacha20_quarter_round( state, 1, 5, 9, 13 ); |
chacha20_quarter_round( state, 2, 6, 10, 14 ); |
chacha20_quarter_round( state, 3, 7, 11, 15 ); |
chacha20_quarter_round( state, 0, 5, 10, 15 ); |
chacha20_quarter_round( state, 1, 6, 11, 12 ); |
chacha20_quarter_round( state, 2, 7, 8, 13 ); |
chacha20_quarter_round( state, 3, 4, 9, 14 ); |
} |
/** |
* \brief Generates a keystream block. |
* |
* \param initial_state The initial ChaCha20 state (key, nonce, counter). |
* \param keystream Generated keystream bytes are written to this buffer. |
*/ |
static void chacha20_block( const uint32_t initial_state[16], |
unsigned char keystream[64] ) |
{ |
uint32_t working_state[16]; |
size_t i; |
memcpy( working_state, |
initial_state, |
CHACHA20_BLOCK_SIZE_BYTES ); |
for( i = 0U; i < 10U; i++ ) |
chacha20_inner_block( working_state ); |
working_state[ 0] += initial_state[ 0]; |
working_state[ 1] += initial_state[ 1]; |
working_state[ 2] += initial_state[ 2]; |
working_state[ 3] += initial_state[ 3]; |
working_state[ 4] += initial_state[ 4]; |
working_state[ 5] += initial_state[ 5]; |
working_state[ 6] += initial_state[ 6]; |
working_state[ 7] += initial_state[ 7]; |
working_state[ 8] += initial_state[ 8]; |
working_state[ 9] += initial_state[ 9]; |
working_state[10] += initial_state[10]; |
working_state[11] += initial_state[11]; |
working_state[12] += initial_state[12]; |
working_state[13] += initial_state[13]; |
working_state[14] += initial_state[14]; |
working_state[15] += initial_state[15]; |
for( i = 0U; i < 16; i++ ) |
{ |
size_t offset = i * 4U; |
keystream[offset ] = (unsigned char)( working_state[i] ); |
keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 ); |
keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 ); |
keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 ); |
} |
mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); |
} |
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) |
{ |
CHACHA20_VALIDATE( ctx != NULL ); |
mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); |
mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); |
/* Initially, there's no keystream bytes available */ |
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; |
} |
void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) |
{ |
if( ctx != NULL ) |
{ |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); |
} |
} |
int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, |
const unsigned char key[32] ) |
{ |
CHACHA20_VALIDATE_RET( ctx != NULL ); |
CHACHA20_VALIDATE_RET( key != NULL ); |
/* ChaCha20 constants - the string "expand 32-byte k" */ |
ctx->state[0] = 0x61707865; |
ctx->state[1] = 0x3320646e; |
ctx->state[2] = 0x79622d32; |
ctx->state[3] = 0x6b206574; |
/* Set key */ |
ctx->state[4] = BYTES_TO_U32_LE( key, 0 ); |
ctx->state[5] = BYTES_TO_U32_LE( key, 4 ); |
ctx->state[6] = BYTES_TO_U32_LE( key, 8 ); |
ctx->state[7] = BYTES_TO_U32_LE( key, 12 ); |
ctx->state[8] = BYTES_TO_U32_LE( key, 16 ); |
ctx->state[9] = BYTES_TO_U32_LE( key, 20 ); |
ctx->state[10] = BYTES_TO_U32_LE( key, 24 ); |
ctx->state[11] = BYTES_TO_U32_LE( key, 28 ); |
return( 0 ); |
} |
int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, |
const unsigned char nonce[12], |
uint32_t counter ) |
{ |
CHACHA20_VALIDATE_RET( ctx != NULL ); |
CHACHA20_VALIDATE_RET( nonce != NULL ); |
/* Counter */ |
ctx->state[12] = counter; |
/* Nonce */ |
ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 ); |
ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 ); |
ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 ); |
mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); |
/* Initially, there's no keystream bytes available */ |
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; |
return( 0 ); |
} |
int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, |
size_t size, |
const unsigned char *input, |
unsigned char *output ) |
{ |
size_t offset = 0U; |
size_t i; |
CHACHA20_VALIDATE_RET( ctx != NULL ); |
CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); |
CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); |
/* Use leftover keystream bytes, if available */ |
while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) |
{ |
output[offset] = input[offset] |
^ ctx->keystream8[ctx->keystream_bytes_used]; |
ctx->keystream_bytes_used++; |
offset++; |
size--; |
} |
/* Process full blocks */ |
while( size >= CHACHA20_BLOCK_SIZE_BYTES ) |
{ |
/* Generate new keystream block and increment counter */ |
chacha20_block( ctx->state, ctx->keystream8 ); |
ctx->state[CHACHA20_CTR_INDEX]++; |
for( i = 0U; i < 64U; i += 8U ) |
{ |
output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; |
output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; |
output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; |
output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; |
output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; |
output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; |
output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; |
output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; |
} |
offset += CHACHA20_BLOCK_SIZE_BYTES; |
size -= CHACHA20_BLOCK_SIZE_BYTES; |
} |
/* Last (partial) block */ |
if( size > 0U ) |
{ |
/* Generate new keystream block and increment counter */ |
chacha20_block( ctx->state, ctx->keystream8 ); |
ctx->state[CHACHA20_CTR_INDEX]++; |
for( i = 0U; i < size; i++) |
{ |
output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; |
} |
ctx->keystream_bytes_used = size; |
} |
return( 0 ); |
} |
int mbedtls_chacha20_crypt( const unsigned char key[32], |
const unsigned char nonce[12], |
uint32_t counter, |
size_t data_len, |
const unsigned char* input, |
unsigned char* output ) |
{ |
mbedtls_chacha20_context ctx; |
int ret; |
CHACHA20_VALIDATE_RET( key != NULL ); |
CHACHA20_VALIDATE_RET( nonce != NULL ); |
CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); |
CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); |
mbedtls_chacha20_init( &ctx ); |
ret = mbedtls_chacha20_setkey( &ctx, key ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); |
cleanup: |
mbedtls_chacha20_free( &ctx ); |
return( ret ); |
} |
#endif /* !MBEDTLS_CHACHA20_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
static const unsigned char test_keys[2][32] = |
{ |
{ |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
}, |
{ |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 |
} |
}; |
static const unsigned char test_nonces[2][12] = |
{ |
{ |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00 |
}, |
{ |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x02 |
} |
}; |
static const uint32_t test_counters[2] = |
{ |
0U, |
1U |
}; |
static const unsigned char test_input[2][375] = |
{ |
{ |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
}, |
{ |
0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, |
0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, |
0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, |
0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, |
0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, |
0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, |
0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, |
0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, |
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, |
0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, |
0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, |
0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, |
0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, |
0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, |
0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, |
0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, |
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, |
0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, |
0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, |
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, |
0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, |
0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, |
0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, |
0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, |
0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, |
0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, |
0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, |
0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, |
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, |
0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, |
0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, |
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, |
0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, |
0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, |
0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, |
0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, |
0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, |
0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, |
0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, |
0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, |
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, |
0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, |
0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, |
0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, |
0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, |
0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, |
0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f |
} |
}; |
static const unsigned char test_output[2][375] = |
{ |
{ |
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, |
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, |
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, |
0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, |
0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, |
0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, |
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, |
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 |
}, |
{ |
0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, |
0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, |
0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, |
0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, |
0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, |
0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, |
0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, |
0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, |
0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, |
0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, |
0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, |
0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, |
0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, |
0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, |
0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, |
0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, |
0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, |
0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, |
0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, |
0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, |
0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, |
0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, |
0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, |
0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, |
0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, |
0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, |
0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, |
0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, |
0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, |
0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, |
0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, |
0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, |
0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, |
0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, |
0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, |
0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, |
0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, |
0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, |
0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, |
0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, |
0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, |
0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, |
0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, |
0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, |
0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, |
0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, |
0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 |
} |
}; |
static const size_t test_lengths[2] = |
{ |
64U, |
375U |
}; |
#define ASSERT( cond, args ) \ |
do \ |
{ \ |
if( ! ( cond ) ) \ |
{ \ |
if( verbose != 0 ) \ |
mbedtls_printf args; \ |
\ |
return( -1 ); \ |
} \ |
} \ |
while( 0 ) |
int mbedtls_chacha20_self_test( int verbose ) |
{ |
unsigned char output[381]; |
unsigned i; |
int ret; |
for( i = 0U; i < 2U; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " ChaCha20 test %u ", i ); |
ret = mbedtls_chacha20_crypt( test_keys[i], |
test_nonces[i], |
test_counters[i], |
test_lengths[i], |
test_input[i], |
output ); |
ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); |
ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), |
( "failed (output)\n" ) ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* !MBEDTLS_CHACHA20_C */ |
/programs/develop/libraries/kos_mbedtls/library/chachapoly.c |
---|
0,0 → 1,542 |
/** |
* \file chachapoly.c |
* |
* \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. |
* |
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CHACHAPOLY_C) |
#include "mbedtls/chachapoly.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_CHACHAPOLY_ALT) |
/* Parameter validation macros */ |
#define CHACHAPOLY_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) |
#define CHACHAPOLY_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#define CHACHAPOLY_STATE_INIT ( 0 ) |
#define CHACHAPOLY_STATE_AAD ( 1 ) |
#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ |
#define CHACHAPOLY_STATE_FINISHED ( 3 ) |
/** |
* \brief Adds nul bytes to pad the AAD for Poly1305. |
* |
* \param ctx The ChaCha20-Poly1305 context. |
*/ |
static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) |
{ |
uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); |
unsigned char zeroes[15]; |
if( partial_block_len == 0U ) |
return( 0 ); |
memset( zeroes, 0, sizeof( zeroes ) ); |
return( mbedtls_poly1305_update( &ctx->poly1305_ctx, |
zeroes, |
16U - partial_block_len ) ); |
} |
/** |
* \brief Adds nul bytes to pad the ciphertext for Poly1305. |
* |
* \param ctx The ChaCha20-Poly1305 context. |
*/ |
static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) |
{ |
uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); |
unsigned char zeroes[15]; |
if( partial_block_len == 0U ) |
return( 0 ); |
memset( zeroes, 0, sizeof( zeroes ) ); |
return( mbedtls_poly1305_update( &ctx->poly1305_ctx, |
zeroes, |
16U - partial_block_len ) ); |
} |
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) |
{ |
CHACHAPOLY_VALIDATE( ctx != NULL ); |
mbedtls_chacha20_init( &ctx->chacha20_ctx ); |
mbedtls_poly1305_init( &ctx->poly1305_ctx ); |
ctx->aad_len = 0U; |
ctx->ciphertext_len = 0U; |
ctx->state = CHACHAPOLY_STATE_INIT; |
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; |
} |
void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_chacha20_free( &ctx->chacha20_ctx ); |
mbedtls_poly1305_free( &ctx->poly1305_ctx ); |
ctx->aad_len = 0U; |
ctx->ciphertext_len = 0U; |
ctx->state = CHACHAPOLY_STATE_INIT; |
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; |
} |
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, |
const unsigned char key[32] ) |
{ |
int ret; |
CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
CHACHAPOLY_VALIDATE_RET( key != NULL ); |
ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); |
return( ret ); |
} |
int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, |
const unsigned char nonce[12], |
mbedtls_chachapoly_mode_t mode ) |
{ |
int ret; |
unsigned char poly1305_key[64]; |
CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
CHACHAPOLY_VALIDATE_RET( nonce != NULL ); |
/* Set counter = 0, will be update to 1 when generating Poly1305 key */ |
ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); |
if( ret != 0 ) |
goto cleanup; |
/* Generate the Poly1305 key by getting the ChaCha20 keystream output with |
* counter = 0. This is the same as encrypting a buffer of zeroes. |
* Only the first 256-bits (32 bytes) of the key is used for Poly1305. |
* The other 256 bits are discarded. |
*/ |
memset( poly1305_key, 0, sizeof( poly1305_key ) ); |
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), |
poly1305_key, poly1305_key ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); |
if( ret == 0 ) |
{ |
ctx->aad_len = 0U; |
ctx->ciphertext_len = 0U; |
ctx->state = CHACHAPOLY_STATE_AAD; |
ctx->mode = mode; |
} |
cleanup: |
mbedtls_platform_zeroize( poly1305_key, 64U ); |
return( ret ); |
} |
int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, |
const unsigned char *aad, |
size_t aad_len ) |
{ |
CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); |
if( ctx->state != CHACHAPOLY_STATE_AAD ) |
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); |
ctx->aad_len += aad_len; |
return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); |
} |
int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, |
size_t len, |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); |
CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); |
if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && |
( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) |
{ |
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); |
} |
if( ctx->state == CHACHAPOLY_STATE_AAD ) |
{ |
ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; |
ret = chachapoly_pad_aad( ctx ); |
if( ret != 0 ) |
return( ret ); |
} |
ctx->ciphertext_len += len; |
if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) |
{ |
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); |
if( ret != 0 ) |
return( ret ); |
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); |
if( ret != 0 ) |
return( ret ); |
} |
else /* DECRYPT */ |
{ |
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); |
if( ret != 0 ) |
return( ret ); |
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); |
if( ret != 0 ) |
return( ret ); |
} |
return( 0 ); |
} |
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, |
unsigned char mac[16] ) |
{ |
int ret; |
unsigned char len_block[16]; |
CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
CHACHAPOLY_VALIDATE_RET( mac != NULL ); |
if( ctx->state == CHACHAPOLY_STATE_INIT ) |
{ |
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); |
} |
if( ctx->state == CHACHAPOLY_STATE_AAD ) |
{ |
ret = chachapoly_pad_aad( ctx ); |
if( ret != 0 ) |
return( ret ); |
} |
else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) |
{ |
ret = chachapoly_pad_ciphertext( ctx ); |
if( ret != 0 ) |
return( ret ); |
} |
ctx->state = CHACHAPOLY_STATE_FINISHED; |
/* The lengths of the AAD and ciphertext are processed by |
* Poly1305 as the final 128-bit block, encoded as little-endian integers. |
*/ |
len_block[ 0] = (unsigned char)( ctx->aad_len ); |
len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 ); |
len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 ); |
len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 ); |
len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 ); |
len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 ); |
len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 ); |
len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 ); |
len_block[ 8] = (unsigned char)( ctx->ciphertext_len ); |
len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 ); |
len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 ); |
len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 ); |
len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 ); |
len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 ); |
len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 ); |
len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 ); |
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); |
if( ret != 0 ) |
return( ret ); |
ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); |
return( ret ); |
} |
static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, |
mbedtls_chachapoly_mode_t mode, |
size_t length, |
const unsigned char nonce[12], |
const unsigned char *aad, |
size_t aad_len, |
const unsigned char *input, |
unsigned char *output, |
unsigned char tag[16] ) |
{ |
int ret; |
ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_chachapoly_update( ctx, length, input, output ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_chachapoly_finish( ctx, tag ); |
cleanup: |
return( ret ); |
} |
int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, |
size_t length, |
const unsigned char nonce[12], |
const unsigned char *aad, |
size_t aad_len, |
const unsigned char *input, |
unsigned char *output, |
unsigned char tag[16] ) |
{ |
CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
CHACHAPOLY_VALIDATE_RET( nonce != NULL ); |
CHACHAPOLY_VALIDATE_RET( tag != NULL ); |
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); |
CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); |
CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); |
return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, |
length, nonce, aad, aad_len, |
input, output, tag ) ); |
} |
int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, |
size_t length, |
const unsigned char nonce[12], |
const unsigned char *aad, |
size_t aad_len, |
const unsigned char tag[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
unsigned char check_tag[16]; |
size_t i; |
int diff; |
CHACHAPOLY_VALIDATE_RET( ctx != NULL ); |
CHACHAPOLY_VALIDATE_RET( nonce != NULL ); |
CHACHAPOLY_VALIDATE_RET( tag != NULL ); |
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); |
CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); |
CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); |
if( ( ret = chachapoly_crypt_and_tag( ctx, |
MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, |
aad, aad_len, input, output, check_tag ) ) != 0 ) |
{ |
return( ret ); |
} |
/* Check tag in "constant-time" */ |
for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) |
diff |= tag[i] ^ check_tag[i]; |
if( diff != 0 ) |
{ |
mbedtls_platform_zeroize( output, length ); |
return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CHACHAPOLY_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
static const unsigned char test_key[1][32] = |
{ |
{ |
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, |
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, |
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, |
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f |
} |
}; |
static const unsigned char test_nonce[1][12] = |
{ |
{ |
0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ |
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ |
} |
}; |
static const unsigned char test_aad[1][12] = |
{ |
{ |
0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, |
0xc4, 0xc5, 0xc6, 0xc7 |
} |
}; |
static const size_t test_aad_len[1] = |
{ |
12U |
}; |
static const unsigned char test_input[1][114] = |
{ |
{ |
0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, |
0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, |
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, |
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, |
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, |
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, |
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, |
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, |
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, |
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, |
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, |
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, |
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, |
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, |
0x74, 0x2e |
} |
}; |
static const unsigned char test_output[1][114] = |
{ |
{ |
0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, |
0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, |
0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, |
0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, |
0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, |
0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, |
0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, |
0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, |
0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, |
0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, |
0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, |
0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, |
0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, |
0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, |
0x61, 0x16 |
} |
}; |
static const size_t test_input_len[1] = |
{ |
114U |
}; |
static const unsigned char test_mac[1][16] = |
{ |
{ |
0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, |
0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 |
} |
}; |
#define ASSERT( cond, args ) \ |
do \ |
{ \ |
if( ! ( cond ) ) \ |
{ \ |
if( verbose != 0 ) \ |
mbedtls_printf args; \ |
\ |
return( -1 ); \ |
} \ |
} \ |
while( 0 ) |
int mbedtls_chachapoly_self_test( int verbose ) |
{ |
mbedtls_chachapoly_context ctx; |
unsigned i; |
int ret; |
unsigned char output[200]; |
unsigned char mac[16]; |
for( i = 0U; i < 1U; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); |
mbedtls_chachapoly_init( &ctx ); |
ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); |
ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); |
ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, |
test_input_len[i], |
test_nonce[i], |
test_aad[i], |
test_aad_len[i], |
test_input[i], |
output, |
mac ); |
ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); |
ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), |
( "failure (wrong output)\n" ) ); |
ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), |
( "failure (wrong MAC)\n" ) ); |
mbedtls_chachapoly_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_CHACHAPOLY_C */ |
/programs/develop/libraries/kos_mbedtls/library/cipher.c |
---|
0,0 → 1,1160 |
/** |
* \file cipher.c |
* |
* \brief Generic cipher wrapper for mbed TLS |
* |
* \author Adriaan de Jong <dejong@fox-it.com> |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CIPHER_C) |
#include "mbedtls/cipher.h" |
#include "mbedtls/cipher_internal.h" |
#include "mbedtls/platform_util.h" |
#include <stdlib.h> |
#include <string.h> |
#if defined(MBEDTLS_CHACHAPOLY_C) |
#include "mbedtls/chachapoly.h" |
#endif |
#if defined(MBEDTLS_GCM_C) |
#include "mbedtls/gcm.h" |
#endif |
#if defined(MBEDTLS_CCM_C) |
#include "mbedtls/ccm.h" |
#endif |
#if defined(MBEDTLS_CHACHA20_C) |
#include "mbedtls/chacha20.h" |
#endif |
#if defined(MBEDTLS_CMAC_C) |
#include "mbedtls/cmac.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#define CIPHER_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) |
#define CIPHER_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) |
/* Compare the contents of two buffers in constant time. |
* Returns 0 if the contents are bitwise identical, otherwise returns |
* a non-zero value. |
* This is currently only used by GCM and ChaCha20+Poly1305. |
*/ |
static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) |
{ |
const unsigned char *p1 = (const unsigned char*) v1; |
const unsigned char *p2 = (const unsigned char*) v2; |
size_t i; |
unsigned char diff; |
for( diff = 0, i = 0; i < len; i++ ) |
diff |= p1[i] ^ p2[i]; |
return( (int)diff ); |
} |
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ |
static int supported_init = 0; |
const int *mbedtls_cipher_list( void ) |
{ |
const mbedtls_cipher_definition_t *def; |
int *type; |
if( ! supported_init ) |
{ |
def = mbedtls_cipher_definitions; |
type = mbedtls_cipher_supported; |
while( def->type != 0 ) |
*type++ = (*def++).type; |
*type = 0; |
supported_init = 1; |
} |
return( mbedtls_cipher_supported ); |
} |
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) |
{ |
const mbedtls_cipher_definition_t *def; |
for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) |
if( def->type == cipher_type ) |
return( def->info ); |
return( NULL ); |
} |
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) |
{ |
const mbedtls_cipher_definition_t *def; |
if( NULL == cipher_name ) |
return( NULL ); |
for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) |
if( ! strcmp( def->info->name, cipher_name ) ) |
return( def->info ); |
return( NULL ); |
} |
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, |
int key_bitlen, |
const mbedtls_cipher_mode_t mode ) |
{ |
const mbedtls_cipher_definition_t *def; |
for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) |
if( def->info->base->cipher == cipher_id && |
def->info->key_bitlen == (unsigned) key_bitlen && |
def->info->mode == mode ) |
return( def->info ); |
return( NULL ); |
} |
void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) |
{ |
CIPHER_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); |
} |
void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) |
{ |
if( ctx == NULL ) |
return; |
#if defined(MBEDTLS_CMAC_C) |
if( ctx->cmac_ctx ) |
{ |
mbedtls_platform_zeroize( ctx->cmac_ctx, |
sizeof( mbedtls_cmac_context_t ) ); |
mbedtls_free( ctx->cmac_ctx ); |
} |
#endif |
if( ctx->cipher_ctx ) |
ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); |
mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); |
} |
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
if( cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); |
if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) |
return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); |
ctx->cipher_info = cipher_info; |
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) |
/* |
* Ignore possible errors caused by a cipher mode that doesn't use padding |
*/ |
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) |
(void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); |
#else |
(void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); |
#endif |
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ |
return( 0 ); |
} |
int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, |
const unsigned char *key, |
int key_bitlen, |
const mbedtls_operation_t operation ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( key != NULL ); |
CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || |
operation == MBEDTLS_DECRYPT ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && |
(int) ctx->cipher_info->key_bitlen != key_bitlen ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
ctx->key_bitlen = key_bitlen; |
ctx->operation = operation; |
/* |
* For OFB, CFB and CTR mode always use the encryption key schedule |
*/ |
if( MBEDTLS_ENCRYPT == operation || |
MBEDTLS_MODE_CFB == ctx->cipher_info->mode || |
MBEDTLS_MODE_OFB == ctx->cipher_info->mode || |
MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) |
{ |
return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, |
ctx->key_bitlen ) ); |
} |
if( MBEDTLS_DECRYPT == operation ) |
return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, |
ctx->key_bitlen ) ); |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, |
const unsigned char *iv, |
size_t iv_len ) |
{ |
size_t actual_iv_size; |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
/* avoid buffer overflow in ctx->iv */ |
if( iv_len > MBEDTLS_MAX_IV_LENGTH ) |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) |
actual_iv_size = iv_len; |
else |
{ |
actual_iv_size = ctx->cipher_info->iv_size; |
/* avoid reading past the end of input buffer */ |
if( actual_iv_size > iv_len ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
#if defined(MBEDTLS_CHACHA20_C) |
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) |
{ |
if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, |
iv, |
0U ) ) /* Initial counter value */ |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
} |
#endif |
if ( actual_iv_size != 0 ) |
{ |
memcpy( ctx->iv, iv, actual_iv_size ); |
ctx->iv_size = actual_iv_size; |
} |
return( 0 ); |
} |
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
ctx->unprocessed_len = 0; |
return( 0 ); |
} |
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) |
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, |
const unsigned char *ad, size_t ad_len ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_GCM_C) |
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) |
{ |
return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, |
ctx->iv, ctx->iv_size, ad, ad_len ) ); |
} |
#endif |
#if defined(MBEDTLS_CHACHAPOLY_C) |
if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) |
{ |
int result; |
mbedtls_chachapoly_mode_t mode; |
mode = ( ctx->operation == MBEDTLS_ENCRYPT ) |
? MBEDTLS_CHACHAPOLY_ENCRYPT |
: MBEDTLS_CHACHAPOLY_DECRYPT; |
result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, |
ctx->iv, |
mode ); |
if ( result != 0 ) |
return( result ); |
return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, |
ad, ad_len ) ); |
} |
#endif |
return( 0 ); |
} |
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ |
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, |
size_t ilen, unsigned char *output, size_t *olen ) |
{ |
int ret; |
size_t block_size; |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); |
CIPHER_VALIDATE_RET( output != NULL ); |
CIPHER_VALIDATE_RET( olen != NULL ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
*olen = 0; |
block_size = mbedtls_cipher_get_block_size( ctx ); |
if ( 0 == block_size ) |
{ |
return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); |
} |
if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) |
{ |
if( ilen != block_size ) |
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); |
*olen = ilen; |
if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, |
ctx->operation, input, output ) ) ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
#if defined(MBEDTLS_GCM_C) |
if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) |
{ |
*olen = ilen; |
return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, |
output ) ); |
} |
#endif |
#if defined(MBEDTLS_CHACHAPOLY_C) |
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) |
{ |
*olen = ilen; |
return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, |
ilen, input, output ) ); |
} |
#endif |
if( input == output && |
( ctx->unprocessed_len != 0 || ilen % block_size ) ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) |
{ |
size_t copy_len = 0; |
/* |
* If there is not enough data for a full block, cache it. |
*/ |
if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && |
ilen <= block_size - ctx->unprocessed_len ) || |
( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && |
ilen < block_size - ctx->unprocessed_len ) || |
( ctx->operation == MBEDTLS_ENCRYPT && |
ilen < block_size - ctx->unprocessed_len ) ) |
{ |
memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, |
ilen ); |
ctx->unprocessed_len += ilen; |
return( 0 ); |
} |
/* |
* Process cached data first |
*/ |
if( 0 != ctx->unprocessed_len ) |
{ |
copy_len = block_size - ctx->unprocessed_len; |
memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, |
copy_len ); |
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, |
ctx->operation, block_size, ctx->iv, |
ctx->unprocessed_data, output ) ) ) |
{ |
return( ret ); |
} |
*olen += block_size; |
output += block_size; |
ctx->unprocessed_len = 0; |
input += copy_len; |
ilen -= copy_len; |
} |
/* |
* Cache final, incomplete block |
*/ |
if( 0 != ilen ) |
{ |
/* Encryption: only cache partial blocks |
* Decryption w/ padding: always keep at least one whole block |
* Decryption w/o padding: only cache partial blocks |
*/ |
copy_len = ilen % block_size; |
if( copy_len == 0 && |
ctx->operation == MBEDTLS_DECRYPT && |
NULL != ctx->add_padding) |
{ |
copy_len = block_size; |
} |
memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), |
copy_len ); |
ctx->unprocessed_len += copy_len; |
ilen -= copy_len; |
} |
/* |
* Process remaining full blocks |
*/ |
if( ilen ) |
{ |
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, |
ctx->operation, ilen, ctx->iv, input, output ) ) ) |
{ |
return( ret ); |
} |
*olen += ilen; |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) |
{ |
if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, |
ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, |
input, output ) ) ) |
{ |
return( ret ); |
} |
*olen = ilen; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) |
{ |
if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, |
ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) |
{ |
return( ret ); |
} |
*olen = ilen; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_OFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) |
{ |
if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, |
ilen, &ctx->unprocessed_len, ctx->iv, |
ctx->unprocessed_data, input, output ) ) ) |
{ |
return( ret ); |
} |
*olen = ilen; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) |
{ |
if( ctx->unprocessed_len > 0 ) { |
/* We can only process an entire data unit at a time. */ |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
} |
ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, |
ctx->operation, ilen, ctx->iv, input, output ); |
if( ret != 0 ) |
{ |
return( ret ); |
} |
*olen = ilen; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) |
{ |
if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, |
ilen, input, output ) ) ) |
{ |
return( ret ); |
} |
*olen = ilen; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_STREAM */ |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) |
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) |
/* |
* PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len |
*/ |
static void add_pkcs_padding( unsigned char *output, size_t output_len, |
size_t data_len ) |
{ |
size_t padding_len = output_len - data_len; |
unsigned char i; |
for( i = 0; i < padding_len; i++ ) |
output[data_len + i] = (unsigned char) padding_len; |
} |
static int get_pkcs_padding( unsigned char *input, size_t input_len, |
size_t *data_len ) |
{ |
size_t i, pad_idx; |
unsigned char padding_len, bad = 0; |
if( NULL == input || NULL == data_len ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
padding_len = input[input_len - 1]; |
*data_len = input_len - padding_len; |
/* Avoid logical || since it results in a branch */ |
bad |= padding_len > input_len; |
bad |= padding_len == 0; |
/* The number of bytes checked must be independent of padding_len, |
* so pick input_len, which is usually 8 or 16 (one block) */ |
pad_idx = input_len - padding_len; |
for( i = 0; i < input_len; i++ ) |
bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); |
return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); |
} |
#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ |
#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) |
/* |
* One and zeros padding: fill with 80 00 ... 00 |
*/ |
static void add_one_and_zeros_padding( unsigned char *output, |
size_t output_len, size_t data_len ) |
{ |
size_t padding_len = output_len - data_len; |
unsigned char i = 0; |
output[data_len] = 0x80; |
for( i = 1; i < padding_len; i++ ) |
output[data_len + i] = 0x00; |
} |
static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, |
size_t *data_len ) |
{ |
size_t i; |
unsigned char done = 0, prev_done, bad; |
if( NULL == input || NULL == data_len ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
bad = 0x80; |
*data_len = 0; |
for( i = input_len; i > 0; i-- ) |
{ |
prev_done = done; |
done |= ( input[i - 1] != 0 ); |
*data_len |= ( i - 1 ) * ( done != prev_done ); |
bad ^= input[i - 1] * ( done != prev_done ); |
} |
return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); |
} |
#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ |
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) |
/* |
* Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length |
*/ |
static void add_zeros_and_len_padding( unsigned char *output, |
size_t output_len, size_t data_len ) |
{ |
size_t padding_len = output_len - data_len; |
unsigned char i = 0; |
for( i = 1; i < padding_len; i++ ) |
output[data_len + i - 1] = 0x00; |
output[output_len - 1] = (unsigned char) padding_len; |
} |
static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, |
size_t *data_len ) |
{ |
size_t i, pad_idx; |
unsigned char padding_len, bad = 0; |
if( NULL == input || NULL == data_len ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
padding_len = input[input_len - 1]; |
*data_len = input_len - padding_len; |
/* Avoid logical || since it results in a branch */ |
bad |= padding_len > input_len; |
bad |= padding_len == 0; |
/* The number of bytes checked must be independent of padding_len */ |
pad_idx = input_len - padding_len; |
for( i = 0; i < input_len - 1; i++ ) |
bad |= input[i] * ( i >= pad_idx ); |
return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); |
} |
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ |
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) |
/* |
* Zero padding: fill with 00 ... 00 |
*/ |
static void add_zeros_padding( unsigned char *output, |
size_t output_len, size_t data_len ) |
{ |
size_t i; |
for( i = data_len; i < output_len; i++ ) |
output[i] = 0x00; |
} |
static int get_zeros_padding( unsigned char *input, size_t input_len, |
size_t *data_len ) |
{ |
size_t i; |
unsigned char done = 0, prev_done; |
if( NULL == input || NULL == data_len ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
*data_len = 0; |
for( i = input_len; i > 0; i-- ) |
{ |
prev_done = done; |
done |= ( input[i-1] != 0 ); |
*data_len |= i * ( done != prev_done ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ |
/* |
* No padding: don't pad :) |
* |
* There is no add_padding function (check for NULL in mbedtls_cipher_finish) |
* but a trivial get_padding function |
*/ |
static int get_no_padding( unsigned char *input, size_t input_len, |
size_t *data_len ) |
{ |
if( NULL == input || NULL == data_len ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
*data_len = input_len; |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ |
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, |
unsigned char *output, size_t *olen ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( output != NULL ); |
CIPHER_VALIDATE_RET( olen != NULL ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
*olen = 0; |
if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || |
MBEDTLS_MODE_OFB == ctx->cipher_info->mode || |
MBEDTLS_MODE_CTR == ctx->cipher_info->mode || |
MBEDTLS_MODE_GCM == ctx->cipher_info->mode || |
MBEDTLS_MODE_XTS == ctx->cipher_info->mode || |
MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) |
{ |
return( 0 ); |
} |
if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || |
( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) |
{ |
return( 0 ); |
} |
if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) |
{ |
if( ctx->unprocessed_len != 0 ) |
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); |
return( 0 ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) |
{ |
int ret = 0; |
if( MBEDTLS_ENCRYPT == ctx->operation ) |
{ |
/* check for 'no padding' mode */ |
if( NULL == ctx->add_padding ) |
{ |
if( 0 != ctx->unprocessed_len ) |
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); |
return( 0 ); |
} |
ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), |
ctx->unprocessed_len ); |
} |
else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) |
{ |
/* |
* For decrypt operations, expect a full block, |
* or an empty block if no padding |
*/ |
if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) |
return( 0 ); |
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); |
} |
/* cipher block */ |
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, |
ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, |
ctx->unprocessed_data, output ) ) ) |
{ |
return( ret ); |
} |
/* Set output size for decryption */ |
if( MBEDTLS_DECRYPT == ctx->operation ) |
return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), |
olen ) ); |
/* Set output size for encryption */ |
*olen = mbedtls_cipher_get_block_size( ctx ); |
return( 0 ); |
} |
#else |
((void) output); |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) |
int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, |
mbedtls_cipher_padding_t mode ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
switch( mode ) |
{ |
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) |
case MBEDTLS_PADDING_PKCS7: |
ctx->add_padding = add_pkcs_padding; |
ctx->get_padding = get_pkcs_padding; |
break; |
#endif |
#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) |
case MBEDTLS_PADDING_ONE_AND_ZEROS: |
ctx->add_padding = add_one_and_zeros_padding; |
ctx->get_padding = get_one_and_zeros_padding; |
break; |
#endif |
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) |
case MBEDTLS_PADDING_ZEROS_AND_LEN: |
ctx->add_padding = add_zeros_and_len_padding; |
ctx->get_padding = get_zeros_and_len_padding; |
break; |
#endif |
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) |
case MBEDTLS_PADDING_ZEROS: |
ctx->add_padding = add_zeros_padding; |
ctx->get_padding = get_zeros_padding; |
break; |
#endif |
case MBEDTLS_PADDING_NONE: |
ctx->add_padding = NULL; |
ctx->get_padding = get_no_padding; |
break; |
default: |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ |
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) |
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, |
unsigned char *tag, size_t tag_len ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if( MBEDTLS_ENCRYPT != ctx->operation ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_GCM_C) |
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) |
return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, |
tag, tag_len ) ); |
#endif |
#if defined(MBEDTLS_CHACHAPOLY_C) |
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) |
{ |
/* Don't allow truncated MAC for Poly1305 */ |
if ( tag_len != 16U ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, |
tag ) ); |
} |
#endif |
return( 0 ); |
} |
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, |
const unsigned char *tag, size_t tag_len ) |
{ |
unsigned char check_tag[16]; |
int ret; |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
if( ctx->cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if( MBEDTLS_DECRYPT != ctx->operation ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
#if defined(MBEDTLS_GCM_C) |
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) |
{ |
if( tag_len > sizeof( check_tag ) ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, |
check_tag, tag_len ) ) ) |
{ |
return( ret ); |
} |
/* Check the tag in "constant-time" */ |
if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) |
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); |
return( 0 ); |
} |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CHACHAPOLY_C) |
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) |
{ |
/* Don't allow truncated MAC for Poly1305 */ |
if ( tag_len != sizeof( check_tag ) ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, |
check_tag ); |
if ( ret != 0 ) |
{ |
return( ret ); |
} |
/* Check the tag in "constant-time" */ |
if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) |
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); |
return( 0 ); |
} |
#endif /* MBEDTLS_CHACHAPOLY_C */ |
return( 0 ); |
} |
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ |
/* |
* Packet-oriented wrapper for non-AEAD modes |
*/ |
int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen ) |
{ |
int ret; |
size_t finish_olen; |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); |
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); |
CIPHER_VALIDATE_RET( output != NULL ); |
CIPHER_VALIDATE_RET( olen != NULL ); |
if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) |
return( ret ); |
*olen += finish_olen; |
return( 0 ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_AEAD) |
/* |
* Packet-oriented encryption for AEAD modes |
*/ |
int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *ad, size_t ad_len, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen, |
unsigned char *tag, size_t tag_len ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( iv != NULL ); |
CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); |
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); |
CIPHER_VALIDATE_RET( output != NULL ); |
CIPHER_VALIDATE_RET( olen != NULL ); |
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
#if defined(MBEDTLS_GCM_C) |
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) |
{ |
*olen = ilen; |
return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, |
iv, iv_len, ad, ad_len, input, output, |
tag_len, tag ) ); |
} |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CCM_C) |
if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) |
{ |
*olen = ilen; |
return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, |
iv, iv_len, ad, ad_len, input, output, |
tag, tag_len ) ); |
} |
#endif /* MBEDTLS_CCM_C */ |
#if defined(MBEDTLS_CHACHAPOLY_C) |
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) |
{ |
/* ChachaPoly has fixed length nonce and MAC (tag) */ |
if ( ( iv_len != ctx->cipher_info->iv_size ) || |
( tag_len != 16U ) ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
*olen = ilen; |
return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, |
ilen, iv, ad, ad_len, input, output, tag ) ); |
} |
#endif /* MBEDTLS_CHACHAPOLY_C */ |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
} |
/* |
* Packet-oriented decryption for AEAD modes |
*/ |
int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, |
const unsigned char *iv, size_t iv_len, |
const unsigned char *ad, size_t ad_len, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen, |
const unsigned char *tag, size_t tag_len ) |
{ |
CIPHER_VALIDATE_RET( ctx != NULL ); |
CIPHER_VALIDATE_RET( iv != NULL ); |
CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); |
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); |
CIPHER_VALIDATE_RET( output != NULL ); |
CIPHER_VALIDATE_RET( olen != NULL ); |
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); |
#if defined(MBEDTLS_GCM_C) |
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) |
{ |
int ret; |
*olen = ilen; |
ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, |
iv, iv_len, ad, ad_len, |
tag, tag_len, input, output ); |
if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) |
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
return( ret ); |
} |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CCM_C) |
if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) |
{ |
int ret; |
*olen = ilen; |
ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, |
iv, iv_len, ad, ad_len, |
input, output, tag, tag_len ); |
if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) |
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
return( ret ); |
} |
#endif /* MBEDTLS_CCM_C */ |
#if defined(MBEDTLS_CHACHAPOLY_C) |
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) |
{ |
int ret; |
/* ChachaPoly has fixed length nonce and MAC (tag) */ |
if ( ( iv_len != ctx->cipher_info->iv_size ) || |
( tag_len != 16U ) ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
*olen = ilen; |
ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, |
iv, ad, ad_len, tag, input, output ); |
if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) |
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
return( ret ); |
} |
#endif /* MBEDTLS_CHACHAPOLY_C */ |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_AEAD */ |
#endif /* MBEDTLS_CIPHER_C */ |
/programs/develop/libraries/kos_mbedtls/library/cipher_wrap.c |
---|
0,0 → 1,2274 |
/** |
* \file cipher_wrap.c |
* |
* \brief Generic cipher wrapper for mbed TLS |
* |
* \author Adriaan de Jong <dejong@fox-it.com> |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CIPHER_C) |
#include "mbedtls/cipher_internal.h" |
#if defined(MBEDTLS_CHACHAPOLY_C) |
#include "mbedtls/chachapoly.h" |
#endif |
#if defined(MBEDTLS_AES_C) |
#include "mbedtls/aes.h" |
#endif |
#if defined(MBEDTLS_ARC4_C) |
#include "mbedtls/arc4.h" |
#endif |
#if defined(MBEDTLS_CAMELLIA_C) |
#include "mbedtls/camellia.h" |
#endif |
#if defined(MBEDTLS_ARIA_C) |
#include "mbedtls/aria.h" |
#endif |
#if defined(MBEDTLS_DES_C) |
#include "mbedtls/des.h" |
#endif |
#if defined(MBEDTLS_BLOWFISH_C) |
#include "mbedtls/blowfish.h" |
#endif |
#if defined(MBEDTLS_CHACHA20_C) |
#include "mbedtls/chacha20.h" |
#endif |
#if defined(MBEDTLS_GCM_C) |
#include "mbedtls/gcm.h" |
#endif |
#if defined(MBEDTLS_CCM_C) |
#include "mbedtls/ccm.h" |
#endif |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
#include <string.h> |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#if defined(MBEDTLS_GCM_C) |
/* shared by all GCM ciphers */ |
static void *gcm_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); |
if( ctx != NULL ) |
mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); |
return( ctx ); |
} |
static void gcm_ctx_free( void *ctx ) |
{ |
mbedtls_gcm_free( ctx ); |
mbedtls_free( ctx ); |
} |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CCM_C) |
/* shared by all CCM ciphers */ |
static void *ccm_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); |
if( ctx != NULL ) |
mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); |
return( ctx ); |
} |
static void ccm_ctx_free( void *ctx ) |
{ |
mbedtls_ccm_free( ctx ); |
mbedtls_free( ctx ); |
} |
#endif /* MBEDTLS_CCM_C */ |
#if defined(MBEDTLS_AES_C) |
static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, |
unsigned char *iv, const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, |
output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, size_t *iv_off, unsigned char *iv, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, |
input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, |
unsigned char *iv, const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, |
iv, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_OFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, |
unsigned char *nonce_counter, unsigned char *stream_block, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, |
stream_block, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, |
const unsigned char data_unit[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
mbedtls_aes_xts_context *xts_ctx = ctx; |
int mode; |
switch( operation ) |
{ |
case MBEDTLS_ENCRYPT: |
mode = MBEDTLS_AES_ENCRYPT; |
break; |
case MBEDTLS_DECRYPT: |
mode = MBEDTLS_AES_DECRYPT; |
break; |
default: |
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
} |
return mbedtls_aes_crypt_xts( xts_ctx, mode, length, |
data_unit, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); |
} |
static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); |
} |
static void * aes_ctx_alloc( void ) |
{ |
mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); |
if( aes == NULL ) |
return( NULL ); |
mbedtls_aes_init( aes ); |
return( aes ); |
} |
static void aes_ctx_free( void *ctx ) |
{ |
mbedtls_aes_free( (mbedtls_aes_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t aes_info = { |
MBEDTLS_CIPHER_ID_AES, |
aes_crypt_ecb_wrap, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
aes_crypt_cbc_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
aes_crypt_cfb128_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
aes_crypt_ofb_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
aes_crypt_ctr_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
aes_setkey_enc_wrap, |
aes_setkey_dec_wrap, |
aes_ctx_alloc, |
aes_ctx_free |
}; |
static const mbedtls_cipher_info_t aes_128_ecb_info = { |
MBEDTLS_CIPHER_AES_128_ECB, |
MBEDTLS_MODE_ECB, |
128, |
"AES-128-ECB", |
0, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_192_ecb_info = { |
MBEDTLS_CIPHER_AES_192_ECB, |
MBEDTLS_MODE_ECB, |
192, |
"AES-192-ECB", |
0, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_ecb_info = { |
MBEDTLS_CIPHER_AES_256_ECB, |
MBEDTLS_MODE_ECB, |
256, |
"AES-256-ECB", |
0, |
0, |
16, |
&aes_info |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const mbedtls_cipher_info_t aes_128_cbc_info = { |
MBEDTLS_CIPHER_AES_128_CBC, |
MBEDTLS_MODE_CBC, |
128, |
"AES-128-CBC", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_192_cbc_info = { |
MBEDTLS_CIPHER_AES_192_CBC, |
MBEDTLS_MODE_CBC, |
192, |
"AES-192-CBC", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_cbc_info = { |
MBEDTLS_CIPHER_AES_256_CBC, |
MBEDTLS_MODE_CBC, |
256, |
"AES-256-CBC", |
16, |
0, |
16, |
&aes_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static const mbedtls_cipher_info_t aes_128_cfb128_info = { |
MBEDTLS_CIPHER_AES_128_CFB128, |
MBEDTLS_MODE_CFB, |
128, |
"AES-128-CFB128", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_192_cfb128_info = { |
MBEDTLS_CIPHER_AES_192_CFB128, |
MBEDTLS_MODE_CFB, |
192, |
"AES-192-CFB128", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_cfb128_info = { |
MBEDTLS_CIPHER_AES_256_CFB128, |
MBEDTLS_MODE_CFB, |
256, |
"AES-256-CFB128", |
16, |
0, |
16, |
&aes_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
static const mbedtls_cipher_info_t aes_128_ofb_info = { |
MBEDTLS_CIPHER_AES_128_OFB, |
MBEDTLS_MODE_OFB, |
128, |
"AES-128-OFB", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_192_ofb_info = { |
MBEDTLS_CIPHER_AES_192_OFB, |
MBEDTLS_MODE_OFB, |
192, |
"AES-192-OFB", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_ofb_info = { |
MBEDTLS_CIPHER_AES_256_OFB, |
MBEDTLS_MODE_OFB, |
256, |
"AES-256-OFB", |
16, |
0, |
16, |
&aes_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_OFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static const mbedtls_cipher_info_t aes_128_ctr_info = { |
MBEDTLS_CIPHER_AES_128_CTR, |
MBEDTLS_MODE_CTR, |
128, |
"AES-128-CTR", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_192_ctr_info = { |
MBEDTLS_CIPHER_AES_192_CTR, |
MBEDTLS_MODE_CTR, |
192, |
"AES-192-CTR", |
16, |
0, |
16, |
&aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_ctr_info = { |
MBEDTLS_CIPHER_AES_256_CTR, |
MBEDTLS_MODE_CTR, |
256, |
"AES-256-CTR", |
16, |
0, |
16, |
&aes_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
mbedtls_aes_xts_context *xts_ctx = ctx; |
return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); |
} |
static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
mbedtls_aes_xts_context *xts_ctx = ctx; |
return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); |
} |
static void *xts_aes_ctx_alloc( void ) |
{ |
mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); |
if( xts_ctx != NULL ) |
mbedtls_aes_xts_init( xts_ctx ); |
return( xts_ctx ); |
} |
static void xts_aes_ctx_free( void *ctx ) |
{ |
mbedtls_aes_xts_context *xts_ctx = ctx; |
if( xts_ctx == NULL ) |
return; |
mbedtls_aes_xts_free( xts_ctx ); |
mbedtls_free( xts_ctx ); |
} |
static const mbedtls_cipher_base_t xts_aes_info = { |
MBEDTLS_CIPHER_ID_AES, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
aes_crypt_xts_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
xts_aes_setkey_enc_wrap, |
xts_aes_setkey_dec_wrap, |
xts_aes_ctx_alloc, |
xts_aes_ctx_free |
}; |
static const mbedtls_cipher_info_t aes_128_xts_info = { |
MBEDTLS_CIPHER_AES_128_XTS, |
MBEDTLS_MODE_XTS, |
256, |
"AES-128-XTS", |
16, |
0, |
16, |
&xts_aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_xts_info = { |
MBEDTLS_CIPHER_AES_256_XTS, |
MBEDTLS_MODE_XTS, |
512, |
"AES-256-XTS", |
16, |
0, |
16, |
&xts_aes_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
#if defined(MBEDTLS_GCM_C) |
static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, |
key, key_bitlen ); |
} |
static const mbedtls_cipher_base_t gcm_aes_info = { |
MBEDTLS_CIPHER_ID_AES, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
gcm_aes_setkey_wrap, |
gcm_aes_setkey_wrap, |
gcm_ctx_alloc, |
gcm_ctx_free, |
}; |
static const mbedtls_cipher_info_t aes_128_gcm_info = { |
MBEDTLS_CIPHER_AES_128_GCM, |
MBEDTLS_MODE_GCM, |
128, |
"AES-128-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_aes_info |
}; |
static const mbedtls_cipher_info_t aes_192_gcm_info = { |
MBEDTLS_CIPHER_AES_192_GCM, |
MBEDTLS_MODE_GCM, |
192, |
"AES-192-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_gcm_info = { |
MBEDTLS_CIPHER_AES_256_GCM, |
MBEDTLS_MODE_GCM, |
256, |
"AES-256-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_aes_info |
}; |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CCM_C) |
static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, |
key, key_bitlen ); |
} |
static const mbedtls_cipher_base_t ccm_aes_info = { |
MBEDTLS_CIPHER_ID_AES, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
ccm_aes_setkey_wrap, |
ccm_aes_setkey_wrap, |
ccm_ctx_alloc, |
ccm_ctx_free, |
}; |
static const mbedtls_cipher_info_t aes_128_ccm_info = { |
MBEDTLS_CIPHER_AES_128_CCM, |
MBEDTLS_MODE_CCM, |
128, |
"AES-128-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_aes_info |
}; |
static const mbedtls_cipher_info_t aes_192_ccm_info = { |
MBEDTLS_CIPHER_AES_192_CCM, |
MBEDTLS_MODE_CCM, |
192, |
"AES-192-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_aes_info |
}; |
static const mbedtls_cipher_info_t aes_256_ccm_info = { |
MBEDTLS_CIPHER_AES_256_CCM, |
MBEDTLS_MODE_CCM, |
256, |
"AES-256-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_aes_info |
}; |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, |
output ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, unsigned char *iv, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, |
input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, size_t *iv_off, unsigned char *iv, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, |
iv_off, iv, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, |
unsigned char *nonce_counter, unsigned char *stream_block, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, |
nonce_counter, stream_block, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); |
} |
static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); |
} |
static void * camellia_ctx_alloc( void ) |
{ |
mbedtls_camellia_context *ctx; |
ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); |
if( ctx == NULL ) |
return( NULL ); |
mbedtls_camellia_init( ctx ); |
return( ctx ); |
} |
static void camellia_ctx_free( void *ctx ) |
{ |
mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t camellia_info = { |
MBEDTLS_CIPHER_ID_CAMELLIA, |
camellia_crypt_ecb_wrap, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
camellia_crypt_cbc_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
camellia_crypt_cfb128_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
camellia_crypt_ctr_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
camellia_setkey_enc_wrap, |
camellia_setkey_dec_wrap, |
camellia_ctx_alloc, |
camellia_ctx_free |
}; |
static const mbedtls_cipher_info_t camellia_128_ecb_info = { |
MBEDTLS_CIPHER_CAMELLIA_128_ECB, |
MBEDTLS_MODE_ECB, |
128, |
"CAMELLIA-128-ECB", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_192_ecb_info = { |
MBEDTLS_CIPHER_CAMELLIA_192_ECB, |
MBEDTLS_MODE_ECB, |
192, |
"CAMELLIA-192-ECB", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_256_ecb_info = { |
MBEDTLS_CIPHER_CAMELLIA_256_ECB, |
MBEDTLS_MODE_ECB, |
256, |
"CAMELLIA-256-ECB", |
16, |
0, |
16, |
&camellia_info |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const mbedtls_cipher_info_t camellia_128_cbc_info = { |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, |
MBEDTLS_MODE_CBC, |
128, |
"CAMELLIA-128-CBC", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_192_cbc_info = { |
MBEDTLS_CIPHER_CAMELLIA_192_CBC, |
MBEDTLS_MODE_CBC, |
192, |
"CAMELLIA-192-CBC", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_256_cbc_info = { |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, |
MBEDTLS_MODE_CBC, |
256, |
"CAMELLIA-256-CBC", |
16, |
0, |
16, |
&camellia_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static const mbedtls_cipher_info_t camellia_128_cfb128_info = { |
MBEDTLS_CIPHER_CAMELLIA_128_CFB128, |
MBEDTLS_MODE_CFB, |
128, |
"CAMELLIA-128-CFB128", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_192_cfb128_info = { |
MBEDTLS_CIPHER_CAMELLIA_192_CFB128, |
MBEDTLS_MODE_CFB, |
192, |
"CAMELLIA-192-CFB128", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_256_cfb128_info = { |
MBEDTLS_CIPHER_CAMELLIA_256_CFB128, |
MBEDTLS_MODE_CFB, |
256, |
"CAMELLIA-256-CFB128", |
16, |
0, |
16, |
&camellia_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static const mbedtls_cipher_info_t camellia_128_ctr_info = { |
MBEDTLS_CIPHER_CAMELLIA_128_CTR, |
MBEDTLS_MODE_CTR, |
128, |
"CAMELLIA-128-CTR", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_192_ctr_info = { |
MBEDTLS_CIPHER_CAMELLIA_192_CTR, |
MBEDTLS_MODE_CTR, |
192, |
"CAMELLIA-192-CTR", |
16, |
0, |
16, |
&camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_256_ctr_info = { |
MBEDTLS_CIPHER_CAMELLIA_256_CTR, |
MBEDTLS_MODE_CTR, |
256, |
"CAMELLIA-256-CTR", |
16, |
0, |
16, |
&camellia_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_GCM_C) |
static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, |
key, key_bitlen ); |
} |
static const mbedtls_cipher_base_t gcm_camellia_info = { |
MBEDTLS_CIPHER_ID_CAMELLIA, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
gcm_camellia_setkey_wrap, |
gcm_camellia_setkey_wrap, |
gcm_ctx_alloc, |
gcm_ctx_free, |
}; |
static const mbedtls_cipher_info_t camellia_128_gcm_info = { |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, |
MBEDTLS_MODE_GCM, |
128, |
"CAMELLIA-128-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_192_gcm_info = { |
MBEDTLS_CIPHER_CAMELLIA_192_GCM, |
MBEDTLS_MODE_GCM, |
192, |
"CAMELLIA-192-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_256_gcm_info = { |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, |
MBEDTLS_MODE_GCM, |
256, |
"CAMELLIA-256-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_camellia_info |
}; |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CCM_C) |
static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, |
key, key_bitlen ); |
} |
static const mbedtls_cipher_base_t ccm_camellia_info = { |
MBEDTLS_CIPHER_ID_CAMELLIA, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
ccm_camellia_setkey_wrap, |
ccm_camellia_setkey_wrap, |
ccm_ctx_alloc, |
ccm_ctx_free, |
}; |
static const mbedtls_cipher_info_t camellia_128_ccm_info = { |
MBEDTLS_CIPHER_CAMELLIA_128_CCM, |
MBEDTLS_MODE_CCM, |
128, |
"CAMELLIA-128-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_192_ccm_info = { |
MBEDTLS_CIPHER_CAMELLIA_192_CCM, |
MBEDTLS_MODE_CCM, |
192, |
"CAMELLIA-192-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_camellia_info |
}; |
static const mbedtls_cipher_info_t camellia_256_ccm_info = { |
MBEDTLS_CIPHER_CAMELLIA_256_CCM, |
MBEDTLS_MODE_CCM, |
256, |
"CAMELLIA-256-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_camellia_info |
}; |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_ARIA_C) |
static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, |
const unsigned char *input, unsigned char *output ) |
{ |
(void) operation; |
return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, |
output ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, unsigned char *iv, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, |
input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, size_t *iv_off, unsigned char *iv, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, |
iv_off, iv, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, |
unsigned char *nonce_counter, unsigned char *stream_block, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, |
nonce_counter, stream_block, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); |
} |
static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); |
} |
static void * aria_ctx_alloc( void ) |
{ |
mbedtls_aria_context *ctx; |
ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); |
if( ctx == NULL ) |
return( NULL ); |
mbedtls_aria_init( ctx ); |
return( ctx ); |
} |
static void aria_ctx_free( void *ctx ) |
{ |
mbedtls_aria_free( (mbedtls_aria_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t aria_info = { |
MBEDTLS_CIPHER_ID_ARIA, |
aria_crypt_ecb_wrap, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
aria_crypt_cbc_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
aria_crypt_cfb128_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
aria_crypt_ctr_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
aria_setkey_enc_wrap, |
aria_setkey_dec_wrap, |
aria_ctx_alloc, |
aria_ctx_free |
}; |
static const mbedtls_cipher_info_t aria_128_ecb_info = { |
MBEDTLS_CIPHER_ARIA_128_ECB, |
MBEDTLS_MODE_ECB, |
128, |
"ARIA-128-ECB", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_192_ecb_info = { |
MBEDTLS_CIPHER_ARIA_192_ECB, |
MBEDTLS_MODE_ECB, |
192, |
"ARIA-192-ECB", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_256_ecb_info = { |
MBEDTLS_CIPHER_ARIA_256_ECB, |
MBEDTLS_MODE_ECB, |
256, |
"ARIA-256-ECB", |
16, |
0, |
16, |
&aria_info |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const mbedtls_cipher_info_t aria_128_cbc_info = { |
MBEDTLS_CIPHER_ARIA_128_CBC, |
MBEDTLS_MODE_CBC, |
128, |
"ARIA-128-CBC", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_192_cbc_info = { |
MBEDTLS_CIPHER_ARIA_192_CBC, |
MBEDTLS_MODE_CBC, |
192, |
"ARIA-192-CBC", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_256_cbc_info = { |
MBEDTLS_CIPHER_ARIA_256_CBC, |
MBEDTLS_MODE_CBC, |
256, |
"ARIA-256-CBC", |
16, |
0, |
16, |
&aria_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static const mbedtls_cipher_info_t aria_128_cfb128_info = { |
MBEDTLS_CIPHER_ARIA_128_CFB128, |
MBEDTLS_MODE_CFB, |
128, |
"ARIA-128-CFB128", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_192_cfb128_info = { |
MBEDTLS_CIPHER_ARIA_192_CFB128, |
MBEDTLS_MODE_CFB, |
192, |
"ARIA-192-CFB128", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_256_cfb128_info = { |
MBEDTLS_CIPHER_ARIA_256_CFB128, |
MBEDTLS_MODE_CFB, |
256, |
"ARIA-256-CFB128", |
16, |
0, |
16, |
&aria_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static const mbedtls_cipher_info_t aria_128_ctr_info = { |
MBEDTLS_CIPHER_ARIA_128_CTR, |
MBEDTLS_MODE_CTR, |
128, |
"ARIA-128-CTR", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_192_ctr_info = { |
MBEDTLS_CIPHER_ARIA_192_CTR, |
MBEDTLS_MODE_CTR, |
192, |
"ARIA-192-CTR", |
16, |
0, |
16, |
&aria_info |
}; |
static const mbedtls_cipher_info_t aria_256_ctr_info = { |
MBEDTLS_CIPHER_ARIA_256_CTR, |
MBEDTLS_MODE_CTR, |
256, |
"ARIA-256-CTR", |
16, |
0, |
16, |
&aria_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_GCM_C) |
static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, |
key, key_bitlen ); |
} |
static const mbedtls_cipher_base_t gcm_aria_info = { |
MBEDTLS_CIPHER_ID_ARIA, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
gcm_aria_setkey_wrap, |
gcm_aria_setkey_wrap, |
gcm_ctx_alloc, |
gcm_ctx_free, |
}; |
static const mbedtls_cipher_info_t aria_128_gcm_info = { |
MBEDTLS_CIPHER_ARIA_128_GCM, |
MBEDTLS_MODE_GCM, |
128, |
"ARIA-128-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_aria_info |
}; |
static const mbedtls_cipher_info_t aria_192_gcm_info = { |
MBEDTLS_CIPHER_ARIA_192_GCM, |
MBEDTLS_MODE_GCM, |
192, |
"ARIA-192-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_aria_info |
}; |
static const mbedtls_cipher_info_t aria_256_gcm_info = { |
MBEDTLS_CIPHER_ARIA_256_GCM, |
MBEDTLS_MODE_GCM, |
256, |
"ARIA-256-GCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&gcm_aria_info |
}; |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CCM_C) |
static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, |
key, key_bitlen ); |
} |
static const mbedtls_cipher_base_t ccm_aria_info = { |
MBEDTLS_CIPHER_ID_ARIA, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
ccm_aria_setkey_wrap, |
ccm_aria_setkey_wrap, |
ccm_ctx_alloc, |
ccm_ctx_free, |
}; |
static const mbedtls_cipher_info_t aria_128_ccm_info = { |
MBEDTLS_CIPHER_ARIA_128_CCM, |
MBEDTLS_MODE_CCM, |
128, |
"ARIA-128-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_aria_info |
}; |
static const mbedtls_cipher_info_t aria_192_ccm_info = { |
MBEDTLS_CIPHER_ARIA_192_CCM, |
MBEDTLS_MODE_CCM, |
192, |
"ARIA-192-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_aria_info |
}; |
static const mbedtls_cipher_info_t aria_256_ccm_info = { |
MBEDTLS_CIPHER_ARIA_256_CCM, |
MBEDTLS_MODE_CCM, |
256, |
"ARIA-256-CCM", |
12, |
MBEDTLS_CIPHER_VARIABLE_IV_LEN, |
16, |
&ccm_aria_info |
}; |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_ARIA_C */ |
#if defined(MBEDTLS_DES_C) |
static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, |
const unsigned char *input, unsigned char *output ) |
{ |
((void) operation); |
return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); |
} |
static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, |
const unsigned char *input, unsigned char *output ) |
{ |
((void) operation); |
return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, |
unsigned char *iv, const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, |
output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, |
unsigned char *iv, const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, |
output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
((void) key_bitlen); |
return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); |
} |
static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
((void) key_bitlen); |
return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); |
} |
static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
((void) key_bitlen); |
return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); |
} |
static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
((void) key_bitlen); |
return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); |
} |
static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
((void) key_bitlen); |
return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); |
} |
static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
((void) key_bitlen); |
return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); |
} |
static void * des_ctx_alloc( void ) |
{ |
mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); |
if( des == NULL ) |
return( NULL ); |
mbedtls_des_init( des ); |
return( des ); |
} |
static void des_ctx_free( void *ctx ) |
{ |
mbedtls_des_free( (mbedtls_des_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void * des3_ctx_alloc( void ) |
{ |
mbedtls_des3_context *des3; |
des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); |
if( des3 == NULL ) |
return( NULL ); |
mbedtls_des3_init( des3 ); |
return( des3 ); |
} |
static void des3_ctx_free( void *ctx ) |
{ |
mbedtls_des3_free( (mbedtls_des3_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t des_info = { |
MBEDTLS_CIPHER_ID_DES, |
des_crypt_ecb_wrap, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
des_crypt_cbc_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
des_setkey_enc_wrap, |
des_setkey_dec_wrap, |
des_ctx_alloc, |
des_ctx_free |
}; |
static const mbedtls_cipher_info_t des_ecb_info = { |
MBEDTLS_CIPHER_DES_ECB, |
MBEDTLS_MODE_ECB, |
MBEDTLS_KEY_LENGTH_DES, |
"DES-ECB", |
8, |
0, |
8, |
&des_info |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const mbedtls_cipher_info_t des_cbc_info = { |
MBEDTLS_CIPHER_DES_CBC, |
MBEDTLS_MODE_CBC, |
MBEDTLS_KEY_LENGTH_DES, |
"DES-CBC", |
8, |
0, |
8, |
&des_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
static const mbedtls_cipher_base_t des_ede_info = { |
MBEDTLS_CIPHER_ID_DES, |
des3_crypt_ecb_wrap, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
des3_crypt_cbc_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
des3_set2key_enc_wrap, |
des3_set2key_dec_wrap, |
des3_ctx_alloc, |
des3_ctx_free |
}; |
static const mbedtls_cipher_info_t des_ede_ecb_info = { |
MBEDTLS_CIPHER_DES_EDE_ECB, |
MBEDTLS_MODE_ECB, |
MBEDTLS_KEY_LENGTH_DES_EDE, |
"DES-EDE-ECB", |
8, |
0, |
8, |
&des_ede_info |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const mbedtls_cipher_info_t des_ede_cbc_info = { |
MBEDTLS_CIPHER_DES_EDE_CBC, |
MBEDTLS_MODE_CBC, |
MBEDTLS_KEY_LENGTH_DES_EDE, |
"DES-EDE-CBC", |
8, |
0, |
8, |
&des_ede_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
static const mbedtls_cipher_base_t des_ede3_info = { |
MBEDTLS_CIPHER_ID_3DES, |
des3_crypt_ecb_wrap, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
des3_crypt_cbc_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
des3_set3key_enc_wrap, |
des3_set3key_dec_wrap, |
des3_ctx_alloc, |
des3_ctx_free |
}; |
static const mbedtls_cipher_info_t des_ede3_ecb_info = { |
MBEDTLS_CIPHER_DES_EDE3_ECB, |
MBEDTLS_MODE_ECB, |
MBEDTLS_KEY_LENGTH_DES_EDE3, |
"DES-EDE3-ECB", |
8, |
0, |
8, |
&des_ede3_info |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const mbedtls_cipher_info_t des_ede3_cbc_info = { |
MBEDTLS_CIPHER_DES_EDE3_CBC, |
MBEDTLS_MODE_CBC, |
MBEDTLS_KEY_LENGTH_DES_EDE3, |
"DES-EDE3-CBC", |
8, |
0, |
8, |
&des_ede3_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_BLOWFISH_C) |
static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, |
output ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, unsigned char *iv, const unsigned char *input, |
unsigned char *output ) |
{ |
return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, |
input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, |
size_t length, size_t *iv_off, unsigned char *iv, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, |
iv_off, iv, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, |
unsigned char *nonce_counter, unsigned char *stream_block, |
const unsigned char *input, unsigned char *output ) |
{ |
return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, |
nonce_counter, stream_block, input, output ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); |
} |
static void * blowfish_ctx_alloc( void ) |
{ |
mbedtls_blowfish_context *ctx; |
ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); |
if( ctx == NULL ) |
return( NULL ); |
mbedtls_blowfish_init( ctx ); |
return( ctx ); |
} |
static void blowfish_ctx_free( void *ctx ) |
{ |
mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t blowfish_info = { |
MBEDTLS_CIPHER_ID_BLOWFISH, |
blowfish_crypt_ecb_wrap, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
blowfish_crypt_cbc_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
blowfish_crypt_cfb64_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
blowfish_crypt_ctr_wrap, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
blowfish_setkey_wrap, |
blowfish_setkey_wrap, |
blowfish_ctx_alloc, |
blowfish_ctx_free |
}; |
static const mbedtls_cipher_info_t blowfish_ecb_info = { |
MBEDTLS_CIPHER_BLOWFISH_ECB, |
MBEDTLS_MODE_ECB, |
128, |
"BLOWFISH-ECB", |
8, |
MBEDTLS_CIPHER_VARIABLE_KEY_LEN, |
8, |
&blowfish_info |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const mbedtls_cipher_info_t blowfish_cbc_info = { |
MBEDTLS_CIPHER_BLOWFISH_CBC, |
MBEDTLS_MODE_CBC, |
128, |
"BLOWFISH-CBC", |
8, |
MBEDTLS_CIPHER_VARIABLE_KEY_LEN, |
8, |
&blowfish_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
static const mbedtls_cipher_info_t blowfish_cfb64_info = { |
MBEDTLS_CIPHER_BLOWFISH_CFB64, |
MBEDTLS_MODE_CFB, |
128, |
"BLOWFISH-CFB64", |
8, |
MBEDTLS_CIPHER_VARIABLE_KEY_LEN, |
8, |
&blowfish_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
static const mbedtls_cipher_info_t blowfish_ctr_info = { |
MBEDTLS_CIPHER_BLOWFISH_CTR, |
MBEDTLS_MODE_CTR, |
128, |
"BLOWFISH-CTR", |
8, |
MBEDTLS_CIPHER_VARIABLE_KEY_LEN, |
8, |
&blowfish_info |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#endif /* MBEDTLS_BLOWFISH_C */ |
#if defined(MBEDTLS_ARC4_C) |
static int arc4_crypt_stream_wrap( void *ctx, size_t length, |
const unsigned char *input, |
unsigned char *output ) |
{ |
return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); |
} |
static int arc4_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
/* we get key_bitlen in bits, arc4 expects it in bytes */ |
if( key_bitlen % 8 != 0 ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); |
return( 0 ); |
} |
static void * arc4_ctx_alloc( void ) |
{ |
mbedtls_arc4_context *ctx; |
ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); |
if( ctx == NULL ) |
return( NULL ); |
mbedtls_arc4_init( ctx ); |
return( ctx ); |
} |
static void arc4_ctx_free( void *ctx ) |
{ |
mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t arc4_base_info = { |
MBEDTLS_CIPHER_ID_ARC4, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
arc4_crypt_stream_wrap, |
#endif |
arc4_setkey_wrap, |
arc4_setkey_wrap, |
arc4_ctx_alloc, |
arc4_ctx_free |
}; |
static const mbedtls_cipher_info_t arc4_128_info = { |
MBEDTLS_CIPHER_ARC4_128, |
MBEDTLS_MODE_STREAM, |
128, |
"ARC4-128", |
0, |
0, |
1, |
&arc4_base_info |
}; |
#endif /* MBEDTLS_ARC4_C */ |
#if defined(MBEDTLS_CHACHA20_C) |
static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
if( key_bitlen != 256U ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
return( 0 ); |
} |
static int chacha20_stream_wrap( void *ctx, size_t length, |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
ret = mbedtls_chacha20_update( ctx, length, input, output ); |
if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
return( ret ); |
} |
static void * chacha20_ctx_alloc( void ) |
{ |
mbedtls_chacha20_context *ctx; |
ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); |
if( ctx == NULL ) |
return( NULL ); |
mbedtls_chacha20_init( ctx ); |
return( ctx ); |
} |
static void chacha20_ctx_free( void *ctx ) |
{ |
mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t chacha20_base_info = { |
MBEDTLS_CIPHER_ID_CHACHA20, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
chacha20_stream_wrap, |
#endif |
chacha20_setkey_wrap, |
chacha20_setkey_wrap, |
chacha20_ctx_alloc, |
chacha20_ctx_free |
}; |
static const mbedtls_cipher_info_t chacha20_info = { |
MBEDTLS_CIPHER_CHACHA20, |
MBEDTLS_MODE_STREAM, |
256, |
"CHACHA20", |
12, |
0, |
1, |
&chacha20_base_info |
}; |
#endif /* MBEDTLS_CHACHA20_C */ |
#if defined(MBEDTLS_CHACHAPOLY_C) |
static int chachapoly_setkey_wrap( void *ctx, |
const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
if( key_bitlen != 256U ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
return( 0 ); |
} |
static void * chachapoly_ctx_alloc( void ) |
{ |
mbedtls_chachapoly_context *ctx; |
ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); |
if( ctx == NULL ) |
return( NULL ); |
mbedtls_chachapoly_init( ctx ); |
return( ctx ); |
} |
static void chachapoly_ctx_free( void *ctx ) |
{ |
mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static const mbedtls_cipher_base_t chachapoly_base_info = { |
MBEDTLS_CIPHER_ID_CHACHA20, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
NULL, |
#endif |
chachapoly_setkey_wrap, |
chachapoly_setkey_wrap, |
chachapoly_ctx_alloc, |
chachapoly_ctx_free |
}; |
static const mbedtls_cipher_info_t chachapoly_info = { |
MBEDTLS_CIPHER_CHACHA20_POLY1305, |
MBEDTLS_MODE_CHACHAPOLY, |
256, |
"CHACHA20-POLY1305", |
12, |
0, |
1, |
&chachapoly_base_info |
}; |
#endif /* MBEDTLS_CHACHAPOLY_C */ |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
static int null_crypt_stream( void *ctx, size_t length, |
const unsigned char *input, |
unsigned char *output ) |
{ |
((void) ctx); |
memmove( output, input, length ); |
return( 0 ); |
} |
static int null_setkey( void *ctx, const unsigned char *key, |
unsigned int key_bitlen ) |
{ |
((void) ctx); |
((void) key); |
((void) key_bitlen); |
return( 0 ); |
} |
static void * null_ctx_alloc( void ) |
{ |
return( (void *) 1 ); |
} |
static void null_ctx_free( void *ctx ) |
{ |
((void) ctx); |
} |
static const mbedtls_cipher_base_t null_base_info = { |
MBEDTLS_CIPHER_ID_NULL, |
NULL, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
NULL, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_STREAM) |
null_crypt_stream, |
#endif |
null_setkey, |
null_setkey, |
null_ctx_alloc, |
null_ctx_free |
}; |
static const mbedtls_cipher_info_t null_cipher_info = { |
MBEDTLS_CIPHER_NULL, |
MBEDTLS_MODE_STREAM, |
0, |
"NULL", |
0, |
0, |
1, |
&null_base_info |
}; |
#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ |
const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = |
{ |
#if defined(MBEDTLS_AES_C) |
{ MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, |
{ MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, |
{ MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, |
{ MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, |
{ MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
{ MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, |
{ MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, |
{ MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
{ MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, |
{ MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, |
{ MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
{ MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, |
{ MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, |
{ MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
{ MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, |
{ MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, |
#endif |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, |
{ MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, |
{ MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, |
#endif |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, |
{ MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, |
{ MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, |
#endif |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_ARC4_C) |
{ MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, |
#endif |
#if defined(MBEDTLS_BLOWFISH_C) |
{ MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
{ MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
{ MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, |
#endif |
#endif /* MBEDTLS_BLOWFISH_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
{ MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
{ MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
{ MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, |
#endif |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, |
#endif |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, |
{ MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, |
#endif |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_ARIA_C) |
{ MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, |
{ MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, |
{ MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, |
{ MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, |
{ MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
{ MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, |
{ MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, |
{ MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
{ MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, |
{ MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, |
{ MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, |
#endif |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, |
{ MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, |
{ MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, |
#endif |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, |
{ MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, |
{ MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, |
#endif |
#endif /* MBEDTLS_ARIA_C */ |
#if defined(MBEDTLS_DES_C) |
{ MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, |
{ MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, |
{ MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, |
{ MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, |
{ MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, |
#endif |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_CHACHA20_C) |
{ MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, |
#endif |
#if defined(MBEDTLS_CHACHAPOLY_C) |
{ MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, |
#endif |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
{ MBEDTLS_CIPHER_NULL, &null_cipher_info }, |
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ |
{ MBEDTLS_CIPHER_NONE, NULL } |
}; |
#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] |
int mbedtls_cipher_supported[NUM_CIPHERS]; |
#endif /* MBEDTLS_CIPHER_C */ |
/programs/develop/libraries/kos_mbedtls/library/cmac.c |
---|
0,0 → 1,1080 |
/** |
* \file cmac.c |
* |
* \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES |
* |
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* References: |
* |
* - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The |
* CMAC Mode for Authentication |
* http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf |
* |
* - RFC 4493 - The AES-CMAC Algorithm |
* https://tools.ietf.org/html/rfc4493 |
* |
* - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message |
* Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) |
* Algorithm for the Internet Key Exchange Protocol (IKE) |
* https://tools.ietf.org/html/rfc4615 |
* |
* Additional test vectors: ISO/IEC 9797-1 |
* |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CMAC_C) |
#include "mbedtls/cmac.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#if defined(MBEDTLS_SELF_TEST) |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_PLATFORM_C */ |
#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) |
/* |
* Multiplication by u in the Galois field of GF(2^n) |
* |
* As explained in NIST SP 800-38B, this can be computed: |
* |
* If MSB(p) = 0, then p = (p << 1) |
* If MSB(p) = 1, then p = (p << 1) ^ R_n |
* with R_64 = 0x1B and R_128 = 0x87 |
* |
* Input and output MUST NOT point to the same buffer |
* Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. |
*/ |
static int cmac_multiply_by_u( unsigned char *output, |
const unsigned char *input, |
size_t blocksize ) |
{ |
const unsigned char R_128 = 0x87; |
const unsigned char R_64 = 0x1B; |
unsigned char R_n, mask; |
unsigned char overflow = 0x00; |
int i; |
if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) |
{ |
R_n = R_128; |
} |
else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) |
{ |
R_n = R_64; |
} |
else |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
for( i = (int)blocksize - 1; i >= 0; i-- ) |
{ |
output[i] = input[i] << 1 | overflow; |
overflow = input[i] >> 7; |
} |
/* mask = ( input[0] >> 7 ) ? 0xff : 0x00 |
* using bit operations to avoid branches */ |
/* MSVC has a warning about unary minus on unsigned, but this is |
* well-defined and precisely what we want to do here */ |
#if defined(_MSC_VER) |
#pragma warning( push ) |
#pragma warning( disable : 4146 ) |
#endif |
mask = - ( input[0] >> 7 ); |
#if defined(_MSC_VER) |
#pragma warning( pop ) |
#endif |
output[ blocksize - 1 ] ^= R_n & mask; |
return( 0 ); |
} |
/* |
* Generate subkeys |
* |
* - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm |
*/ |
static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, |
unsigned char* K1, unsigned char* K2 ) |
{ |
int ret; |
unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; |
size_t olen, block_size; |
mbedtls_platform_zeroize( L, sizeof( L ) ); |
block_size = ctx->cipher_info->block_size; |
/* Calculate Ek(0) */ |
if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) |
goto exit; |
/* |
* Generate K1 and K2 |
*/ |
if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) |
goto exit; |
if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_platform_zeroize( L, sizeof( L ) ); |
return( ret ); |
} |
#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ |
#if !defined(MBEDTLS_CMAC_ALT) |
static void cmac_xor_block( unsigned char *output, const unsigned char *input1, |
const unsigned char *input2, |
const size_t block_size ) |
{ |
size_t idx; |
for( idx = 0; idx < block_size; idx++ ) |
output[ idx ] = input1[ idx ] ^ input2[ idx ]; |
} |
/* |
* Create padded last block from (partial) last block. |
* |
* We can't use the padding option from the cipher layer, as it only works for |
* CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. |
*/ |
static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], |
size_t padded_block_len, |
const unsigned char *last_block, |
size_t last_block_len ) |
{ |
size_t j; |
for( j = 0; j < padded_block_len; j++ ) |
{ |
if( j < last_block_len ) |
padded_block[j] = last_block[j]; |
else if( j == last_block_len ) |
padded_block[j] = 0x80; |
else |
padded_block[j] = 0x00; |
} |
} |
int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, |
const unsigned char *key, size_t keybits ) |
{ |
mbedtls_cipher_type_t type; |
mbedtls_cmac_context_t *cmac_ctx; |
int retval; |
if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, |
MBEDTLS_ENCRYPT ) ) != 0 ) |
return( retval ); |
type = ctx->cipher_info->type; |
switch( type ) |
{ |
case MBEDTLS_CIPHER_AES_128_ECB: |
case MBEDTLS_CIPHER_AES_192_ECB: |
case MBEDTLS_CIPHER_AES_256_ECB: |
case MBEDTLS_CIPHER_DES_EDE3_ECB: |
break; |
default: |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
/* Allocated and initialise in the cipher context memory for the CMAC |
* context */ |
cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); |
if( cmac_ctx == NULL ) |
return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); |
ctx->cmac_ctx = cmac_ctx; |
mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); |
return 0; |
} |
int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, |
const unsigned char *input, size_t ilen ) |
{ |
mbedtls_cmac_context_t* cmac_ctx; |
unsigned char *state; |
int ret = 0; |
size_t n, j, olen, block_size; |
if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || |
ctx->cmac_ctx == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
cmac_ctx = ctx->cmac_ctx; |
block_size = ctx->cipher_info->block_size; |
state = ctx->cmac_ctx->state; |
/* Is there data still to process from the last call, that's greater in |
* size than a block? */ |
if( cmac_ctx->unprocessed_len > 0 && |
ilen > block_size - cmac_ctx->unprocessed_len ) |
{ |
memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], |
input, |
block_size - cmac_ctx->unprocessed_len ); |
cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); |
if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, |
&olen ) ) != 0 ) |
{ |
goto exit; |
} |
input += block_size - cmac_ctx->unprocessed_len; |
ilen -= block_size - cmac_ctx->unprocessed_len; |
cmac_ctx->unprocessed_len = 0; |
} |
/* n is the number of blocks including any final partial block */ |
n = ( ilen + block_size - 1 ) / block_size; |
/* Iterate across the input data in block sized chunks, excluding any |
* final partial or complete block */ |
for( j = 1; j < n; j++ ) |
{ |
cmac_xor_block( state, input, state, block_size ); |
if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, |
&olen ) ) != 0 ) |
goto exit; |
ilen -= block_size; |
input += block_size; |
} |
/* If there is data left over that wasn't aligned to a block */ |
if( ilen > 0 ) |
{ |
memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], |
input, |
ilen ); |
cmac_ctx->unprocessed_len += ilen; |
} |
exit: |
return( ret ); |
} |
int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, |
unsigned char *output ) |
{ |
mbedtls_cmac_context_t* cmac_ctx; |
unsigned char *state, *last_block; |
unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; |
unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; |
unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; |
int ret; |
size_t olen, block_size; |
if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || |
output == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
cmac_ctx = ctx->cmac_ctx; |
block_size = ctx->cipher_info->block_size; |
state = cmac_ctx->state; |
mbedtls_platform_zeroize( K1, sizeof( K1 ) ); |
mbedtls_platform_zeroize( K2, sizeof( K2 ) ); |
cmac_generate_subkeys( ctx, K1, K2 ); |
last_block = cmac_ctx->unprocessed_block; |
/* Calculate last block */ |
if( cmac_ctx->unprocessed_len < block_size ) |
{ |
cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); |
cmac_xor_block( M_last, M_last, K2, block_size ); |
} |
else |
{ |
/* Last block is complete block */ |
cmac_xor_block( M_last, last_block, K1, block_size ); |
} |
cmac_xor_block( state, M_last, state, block_size ); |
if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, |
&olen ) ) != 0 ) |
{ |
goto exit; |
} |
memcpy( output, state, block_size ); |
exit: |
/* Wipe the generated keys on the stack, and any other transients to avoid |
* side channel leakage */ |
mbedtls_platform_zeroize( K1, sizeof( K1 ) ); |
mbedtls_platform_zeroize( K2, sizeof( K2 ) ); |
cmac_ctx->unprocessed_len = 0; |
mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, |
sizeof( cmac_ctx->unprocessed_block ) ); |
mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); |
return( ret ); |
} |
int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) |
{ |
mbedtls_cmac_context_t* cmac_ctx; |
if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
cmac_ctx = ctx->cmac_ctx; |
/* Reset the internal state */ |
cmac_ctx->unprocessed_len = 0; |
mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, |
sizeof( cmac_ctx->unprocessed_block ) ); |
mbedtls_platform_zeroize( cmac_ctx->state, |
sizeof( cmac_ctx->state ) ); |
return( 0 ); |
} |
int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, |
const unsigned char *key, size_t keylen, |
const unsigned char *input, size_t ilen, |
unsigned char *output ) |
{ |
mbedtls_cipher_context_t ctx; |
int ret; |
if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
mbedtls_cipher_init( &ctx ); |
if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) |
goto exit; |
ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_cipher_cmac_finish( &ctx, output ); |
exit: |
mbedtls_cipher_free( &ctx ); |
return( ret ); |
} |
#if defined(MBEDTLS_AES_C) |
/* |
* Implementation of AES-CMAC-PRF-128 defined in RFC 4615 |
*/ |
int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, |
const unsigned char *input, size_t in_len, |
unsigned char *output ) |
{ |
int ret; |
const mbedtls_cipher_info_t *cipher_info; |
unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; |
unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; |
if( key == NULL || input == NULL || output == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); |
if( cipher_info == NULL ) |
{ |
/* Failing at this point must be due to a build issue */ |
ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; |
goto exit; |
} |
if( key_length == MBEDTLS_AES_BLOCK_SIZE ) |
{ |
/* Use key as is */ |
memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); |
} |
else |
{ |
memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); |
ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, |
key_length, int_key ); |
if( ret != 0 ) |
goto exit; |
} |
ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, |
output ); |
exit: |
mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); |
return( ret ); |
} |
#endif /* MBEDTLS_AES_C */ |
#endif /* !MBEDTLS_CMAC_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* CMAC test data for SP800-38B |
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf |
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf |
* |
* AES-CMAC-PRF-128 test data from RFC 4615 |
* https://tools.ietf.org/html/rfc4615#page-4 |
*/ |
#define NB_CMAC_TESTS_PER_KEY 4 |
#define NB_PRF_TESTS 3 |
#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) |
/* All CMAC test inputs are truncated from the same 64 byte buffer. */ |
static const unsigned char test_message[] = { |
/* PT */ |
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, |
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, |
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, |
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, |
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, |
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, |
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, |
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 |
}; |
#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ |
#if defined(MBEDTLS_AES_C) |
/* Truncation point of message for AES CMAC tests */ |
static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { |
/* Mlen */ |
0, |
16, |
20, |
64 |
}; |
/* CMAC-AES128 Test Data */ |
static const unsigned char aes_128_key[16] = { |
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, |
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c |
}; |
static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { |
{ |
/* K1 */ |
0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, |
0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde |
}, |
{ |
/* K2 */ |
0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, |
0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b |
} |
}; |
static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { |
{ |
/* Example #1 */ |
0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, |
0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 |
}, |
{ |
/* Example #2 */ |
0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, |
0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c |
}, |
{ |
/* Example #3 */ |
0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, |
0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde |
}, |
{ |
/* Example #4 */ |
0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, |
0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe |
} |
}; |
/* CMAC-AES192 Test Data */ |
static const unsigned char aes_192_key[24] = { |
0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, |
0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, |
0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b |
}; |
static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { |
{ |
/* K1 */ |
0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, |
0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 |
}, |
{ |
/* K2 */ |
0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, |
0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c |
} |
}; |
static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { |
{ |
/* Example #1 */ |
0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, |
0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 |
}, |
{ |
/* Example #2 */ |
0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, |
0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 |
}, |
{ |
/* Example #3 */ |
0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, |
0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 |
}, |
{ |
/* Example #4 */ |
0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, |
0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 |
} |
}; |
/* CMAC-AES256 Test Data */ |
static const unsigned char aes_256_key[32] = { |
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, |
0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, |
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, |
0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 |
}; |
static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { |
{ |
/* K1 */ |
0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, |
0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f |
}, |
{ |
/* K2 */ |
0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, |
0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 |
} |
}; |
static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { |
{ |
/* Example #1 */ |
0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, |
0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 |
}, |
{ |
/* Example #2 */ |
0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, |
0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c |
}, |
{ |
/* Example #3 */ |
0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, |
0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 |
}, |
{ |
/* Example #4 */ |
0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, |
0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 |
} |
}; |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_DES_C) |
/* Truncation point of message for 3DES CMAC tests */ |
static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { |
0, |
16, |
20, |
32 |
}; |
/* CMAC-TDES (Generation) - 2 Key Test Data */ |
static const unsigned char des3_2key_key[24] = { |
/* Key1 */ |
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
/* Key2 */ |
0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, |
/* Key3 */ |
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef |
}; |
static const unsigned char des3_2key_subkeys[2][8] = { |
{ |
/* K1 */ |
0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 |
}, |
{ |
/* K2 */ |
0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 |
} |
}; |
static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { |
{ |
/* Sample #1 */ |
0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 |
}, |
{ |
/* Sample #2 */ |
0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b |
}, |
{ |
/* Sample #3 */ |
0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 |
}, |
{ |
/* Sample #4 */ |
0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb |
} |
}; |
/* CMAC-TDES (Generation) - 3 Key Test Data */ |
static const unsigned char des3_3key_key[24] = { |
/* Key1 */ |
0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, |
/* Key2 */ |
0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, |
/* Key3 */ |
0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 |
}; |
static const unsigned char des3_3key_subkeys[2][8] = { |
{ |
/* K1 */ |
0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 |
}, |
{ |
/* K2 */ |
0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b |
} |
}; |
static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { |
{ |
/* Sample #1 */ |
0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 |
}, |
{ |
/* Sample #2 */ |
0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 |
}, |
{ |
/* Sample #3 */ |
0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 |
}, |
{ |
/* Sample #4 */ |
0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 |
} |
}; |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_AES_C) |
/* AES AES-CMAC-PRF-128 Test Data */ |
static const unsigned char PRFK[] = { |
/* Key */ |
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
0xed, 0xcb |
}; |
/* Sizes in bytes */ |
static const size_t PRFKlen[NB_PRF_TESTS] = { |
18, |
16, |
10 |
}; |
/* Message */ |
static const unsigned char PRFM[] = { |
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
0x10, 0x11, 0x12, 0x13 |
}; |
static const unsigned char PRFT[NB_PRF_TESTS][16] = { |
{ |
0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, |
0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a |
}, |
{ |
0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, |
0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d |
}, |
{ |
0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, |
0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d |
} |
}; |
#endif /* MBEDTLS_AES_C */ |
static int cmac_test_subkeys( int verbose, |
const char* testname, |
const unsigned char* key, |
int keybits, |
const unsigned char* subkeys, |
mbedtls_cipher_type_t cipher_type, |
int block_size, |
int num_tests ) |
{ |
int i, ret = 0; |
mbedtls_cipher_context_t ctx; |
const mbedtls_cipher_info_t *cipher_info; |
unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; |
unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; |
cipher_info = mbedtls_cipher_info_from_type( cipher_type ); |
if( cipher_info == NULL ) |
{ |
/* Failing at this point must be due to a build issue */ |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
} |
for( i = 0; i < num_tests; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); |
mbedtls_cipher_init( &ctx ); |
if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "test execution failed\n" ); |
goto cleanup; |
} |
if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, |
MBEDTLS_ENCRYPT ) ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "test execution failed\n" ); |
goto cleanup; |
} |
ret = cmac_generate_subkeys( &ctx, K1, K2 ); |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
goto cleanup; |
} |
if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || |
( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
mbedtls_cipher_free( &ctx ); |
} |
ret = 0; |
goto exit; |
cleanup: |
mbedtls_cipher_free( &ctx ); |
exit: |
return( ret ); |
} |
static int cmac_test_wth_cipher( int verbose, |
const char* testname, |
const unsigned char* key, |
int keybits, |
const unsigned char* messages, |
const unsigned int message_lengths[4], |
const unsigned char* expected_result, |
mbedtls_cipher_type_t cipher_type, |
int block_size, |
int num_tests ) |
{ |
const mbedtls_cipher_info_t *cipher_info; |
int i, ret = 0; |
unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; |
cipher_info = mbedtls_cipher_info_from_type( cipher_type ); |
if( cipher_info == NULL ) |
{ |
/* Failing at this point must be due to a build issue */ |
ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; |
goto exit; |
} |
for( i = 0; i < num_tests; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); |
if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, |
message_lengths[i], output ) ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
goto exit; |
} |
if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
ret = 0; |
exit: |
return( ret ); |
} |
#if defined(MBEDTLS_AES_C) |
static int test_aes128_cmac_prf( int verbose ) |
{ |
int i; |
int ret; |
unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; |
for( i = 0; i < NB_PRF_TESTS; i++ ) |
{ |
mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); |
ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); |
if( ret != 0 || |
memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( ret ); |
} |
else if( verbose != 0 ) |
{ |
mbedtls_printf( "passed\n" ); |
} |
} |
return( ret ); |
} |
#endif /* MBEDTLS_AES_C */ |
int mbedtls_cmac_self_test( int verbose ) |
{ |
int ret; |
#if defined(MBEDTLS_AES_C) |
/* AES-128 */ |
if( ( ret = cmac_test_subkeys( verbose, |
"AES 128", |
aes_128_key, |
128, |
(const unsigned char*)aes_128_subkeys, |
MBEDTLS_CIPHER_AES_128_ECB, |
MBEDTLS_AES_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = cmac_test_wth_cipher( verbose, |
"AES 128", |
aes_128_key, |
128, |
test_message, |
aes_message_lengths, |
(const unsigned char*)aes_128_expected_result, |
MBEDTLS_CIPHER_AES_128_ECB, |
MBEDTLS_AES_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
/* AES-192 */ |
if( ( ret = cmac_test_subkeys( verbose, |
"AES 192", |
aes_192_key, |
192, |
(const unsigned char*)aes_192_subkeys, |
MBEDTLS_CIPHER_AES_192_ECB, |
MBEDTLS_AES_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = cmac_test_wth_cipher( verbose, |
"AES 192", |
aes_192_key, |
192, |
test_message, |
aes_message_lengths, |
(const unsigned char*)aes_192_expected_result, |
MBEDTLS_CIPHER_AES_192_ECB, |
MBEDTLS_AES_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
/* AES-256 */ |
if( ( ret = cmac_test_subkeys( verbose, |
"AES 256", |
aes_256_key, |
256, |
(const unsigned char*)aes_256_subkeys, |
MBEDTLS_CIPHER_AES_256_ECB, |
MBEDTLS_AES_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = cmac_test_wth_cipher ( verbose, |
"AES 256", |
aes_256_key, |
256, |
test_message, |
aes_message_lengths, |
(const unsigned char*)aes_256_expected_result, |
MBEDTLS_CIPHER_AES_256_ECB, |
MBEDTLS_AES_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_DES_C) |
/* 3DES 2 key */ |
if( ( ret = cmac_test_subkeys( verbose, |
"3DES 2 key", |
des3_2key_key, |
192, |
(const unsigned char*)des3_2key_subkeys, |
MBEDTLS_CIPHER_DES_EDE3_ECB, |
MBEDTLS_DES3_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = cmac_test_wth_cipher( verbose, |
"3DES 2 key", |
des3_2key_key, |
192, |
test_message, |
des3_message_lengths, |
(const unsigned char*)des3_2key_expected_result, |
MBEDTLS_CIPHER_DES_EDE3_ECB, |
MBEDTLS_DES3_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
/* 3DES 3 key */ |
if( ( ret = cmac_test_subkeys( verbose, |
"3DES 3 key", |
des3_3key_key, |
192, |
(const unsigned char*)des3_3key_subkeys, |
MBEDTLS_CIPHER_DES_EDE3_ECB, |
MBEDTLS_DES3_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = cmac_test_wth_cipher( verbose, |
"3DES 3 key", |
des3_3key_key, |
192, |
test_message, |
des3_message_lengths, |
(const unsigned char*)des3_3key_expected_result, |
MBEDTLS_CIPHER_DES_EDE3_ECB, |
MBEDTLS_DES3_BLOCK_SIZE, |
NB_CMAC_TESTS_PER_KEY ) ) != 0 ) |
{ |
return( ret ); |
} |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_AES_C) |
if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) |
return( ret ); |
#endif /* MBEDTLS_AES_C */ |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_CMAC_C */ |
/programs/develop/libraries/kos_mbedtls/library/ctr_drbg.c |
---|
0,0 → 1,724 |
/* |
* CTR_DRBG implementation based on AES-256 (NIST SP 800-90) |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The NIST SP 800-90 DRBGs are described in the following publication. |
* |
* http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_CTR_DRBG_C) |
#include "mbedtls/ctr_drbg.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_FS_IO) |
#include <stdio.h> |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
/* |
* CTR_DRBG context initialization |
*/ |
void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &ctx->mutex ); |
#endif |
} |
void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &ctx->mutex ); |
#endif |
mbedtls_aes_free( &ctx->aes_ctx ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); |
} |
void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) |
{ |
ctx->prediction_resistance = resistance; |
} |
void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) |
{ |
ctx->entropy_len = len; |
} |
void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) |
{ |
ctx->reseed_interval = interval; |
} |
static int block_cipher_df( unsigned char *output, |
const unsigned char *data, size_t data_len ) |
{ |
unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; |
unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; |
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; |
unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; |
unsigned char *p, *iv; |
mbedtls_aes_context aes_ctx; |
int ret = 0; |
int i, j; |
size_t buf_len, use_len; |
if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) |
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); |
memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); |
mbedtls_aes_init( &aes_ctx ); |
/* |
* Construct IV (16 bytes) and S in buffer |
* IV = Counter (in 32-bits) padded to 16 with zeroes |
* S = Length input string (in 32-bits) || Length of output (in 32-bits) || |
* data || 0x80 |
* (Total is padded to a multiple of 16-bytes with zeroes) |
*/ |
p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; |
*p++ = ( data_len >> 24 ) & 0xff; |
*p++ = ( data_len >> 16 ) & 0xff; |
*p++ = ( data_len >> 8 ) & 0xff; |
*p++ = ( data_len ) & 0xff; |
p += 3; |
*p++ = MBEDTLS_CTR_DRBG_SEEDLEN; |
memcpy( p, data, data_len ); |
p[data_len] = 0x80; |
buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; |
for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) |
key[i] = i; |
if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) |
{ |
goto exit; |
} |
/* |
* Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data |
*/ |
for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) |
{ |
p = buf; |
memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); |
use_len = buf_len; |
while( use_len > 0 ) |
{ |
for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) |
chain[i] ^= p[i]; |
p += MBEDTLS_CTR_DRBG_BLOCKSIZE; |
use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? |
MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; |
if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 ) |
{ |
goto exit; |
} |
} |
memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); |
/* |
* Update IV |
*/ |
buf[3]++; |
} |
/* |
* Do final encryption with reduced data |
*/ |
if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) |
{ |
goto exit; |
} |
iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; |
p = output; |
for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) |
{ |
if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) |
{ |
goto exit; |
} |
memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); |
p += MBEDTLS_CTR_DRBG_BLOCKSIZE; |
} |
exit: |
mbedtls_aes_free( &aes_ctx ); |
/* |
* tidy up the stack |
*/ |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); |
mbedtls_platform_zeroize( key, sizeof( key ) ); |
mbedtls_platform_zeroize( chain, sizeof( chain ) ); |
if( 0 != ret ) |
{ |
/* |
* wipe partial seed from memory |
*/ |
mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); |
} |
return( ret ); |
} |
/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) |
* ctr_drbg_update_internal(ctx, provided_data) |
* implements |
* CTR_DRBG_Update(provided_data, Key, V) |
* with inputs and outputs |
* ctx->aes_ctx = Key |
* ctx->counter = V |
*/ |
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, |
const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) |
{ |
unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; |
unsigned char *p = tmp; |
int i, j; |
int ret = 0; |
memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); |
for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) |
{ |
/* |
* Increase counter |
*/ |
for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) |
if( ++ctx->counter[i - 1] != 0 ) |
break; |
/* |
* Crypt counter block |
*/ |
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) |
goto exit; |
p += MBEDTLS_CTR_DRBG_BLOCKSIZE; |
} |
for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) |
tmp[i] ^= data[i]; |
/* |
* Update key and counter |
*/ |
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) |
goto exit; |
memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); |
exit: |
mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); |
return( ret ); |
} |
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) |
* mbedtls_ctr_drbg_update(ctx, additional, add_len) |
* implements |
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, |
* security_strength) -> initial_working_state |
* with inputs |
* ctx->counter = all-bits-0 |
* ctx->aes_ctx = context from all-bits-0 key |
* additional[:add_len] = entropy_input || nonce || personalization_string |
* and with outputs |
* ctx = initial_working_state |
*/ |
int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, |
const unsigned char *additional, |
size_t add_len ) |
{ |
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; |
int ret; |
if( add_len == 0 ) |
return( 0 ); |
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) |
goto exit; |
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, |
const unsigned char *additional, |
size_t add_len ) |
{ |
/* MAX_INPUT would be more logical here, but we have to match |
* block_cipher_df()'s limits since we can't propagate errors */ |
if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) |
add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; |
(void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); |
} |
#endif /* MBEDTLS_DEPRECATED_REMOVED */ |
/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) |
* mbedtls_ctr_drbg_reseed(ctx, additional, len) |
* implements |
* CTR_DRBG_Reseed(working_state, entropy_input, additional_input) |
* -> new_working_state |
* with inputs |
* ctx contains working_state |
* additional[:len] = additional_input |
* and entropy_input comes from calling ctx->f_entropy |
* and with output |
* ctx contains new_working_state |
*/ |
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, |
const unsigned char *additional, size_t len ) |
{ |
unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; |
size_t seedlen = 0; |
int ret; |
if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || |
len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) |
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); |
memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); |
/* |
* Gather entropy_len bytes of entropy to seed state |
*/ |
if( 0 != ctx->f_entropy( ctx->p_entropy, seed, |
ctx->entropy_len ) ) |
{ |
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); |
} |
seedlen += ctx->entropy_len; |
/* |
* Add additional data |
*/ |
if( additional && len ) |
{ |
memcpy( seed + seedlen, additional, len ); |
seedlen += len; |
} |
/* |
* Reduce to 384 bits |
*/ |
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) |
goto exit; |
/* |
* Update state |
*/ |
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) |
goto exit; |
ctx->reseed_counter = 1; |
exit: |
mbedtls_platform_zeroize( seed, sizeof( seed ) ); |
return( ret ); |
} |
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) |
* mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) |
* implements |
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, |
* security_strength) -> initial_working_state |
* with inputs |
* custom[:len] = nonce || personalization_string |
* where entropy_input comes from f_entropy for ctx->entropy_len bytes |
* and with outputs |
* ctx = initial_working_state |
*/ |
int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, |
int (*f_entropy)(void *, unsigned char *, size_t), |
void *p_entropy, |
const unsigned char *custom, |
size_t len ) |
{ |
int ret; |
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; |
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); |
mbedtls_aes_init( &ctx->aes_ctx ); |
ctx->f_entropy = f_entropy; |
ctx->p_entropy = p_entropy; |
if( ctx->entropy_len == 0 ) |
ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; |
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; |
/* |
* Initialize with an empty key |
*/ |
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
/* Backward compatibility wrapper */ |
int mbedtls_ctr_drbg_seed_entropy_len( |
mbedtls_ctr_drbg_context *ctx, |
int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, |
const unsigned char *custom, size_t len, |
size_t entropy_len ) |
{ |
mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len ); |
return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) ); |
} |
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) |
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) |
* implements |
* CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) |
* -> working_state_after_reseed |
* if required, then |
* CTR_DRBG_Generate(working_state_after_reseed, |
* requested_number_of_bits, additional_input) |
* -> status, returned_bits, new_working_state |
* with inputs |
* ctx contains working_state |
* requested_number_of_bits = 8 * output_len |
* additional[:add_len] = additional_input |
* and entropy_input comes from calling ctx->f_entropy |
* and with outputs |
* status = SUCCESS (this function does the reseed internally) |
* returned_bits = output[:output_len] |
* ctx contains new_working_state |
*/ |
int mbedtls_ctr_drbg_random_with_add( void *p_rng, |
unsigned char *output, size_t output_len, |
const unsigned char *additional, size_t add_len ) |
{ |
int ret = 0; |
mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; |
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; |
unsigned char *p = output; |
unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; |
int i; |
size_t use_len; |
if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) |
return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); |
if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) |
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); |
memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); |
if( ctx->reseed_counter > ctx->reseed_interval || |
ctx->prediction_resistance ) |
{ |
if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) |
{ |
return( ret ); |
} |
add_len = 0; |
} |
if( add_len > 0 ) |
{ |
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) |
goto exit; |
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) |
goto exit; |
} |
while( output_len > 0 ) |
{ |
/* |
* Increase counter |
*/ |
for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) |
if( ++ctx->counter[i - 1] != 0 ) |
break; |
/* |
* Crypt counter block |
*/ |
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) |
goto exit; |
use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : |
output_len; |
/* |
* Copy random block to destination |
*/ |
memcpy( p, tmp, use_len ); |
p += use_len; |
output_len -= use_len; |
} |
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) |
goto exit; |
ctx->reseed_counter++; |
exit: |
mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); |
mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); |
return( ret ); |
} |
int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) |
{ |
int ret; |
mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
#if defined(MBEDTLS_FS_IO) |
int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) |
{ |
int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; |
FILE *f; |
unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; |
if( ( f = fopen( path, "wb" ) ) == NULL ) |
return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); |
if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) |
goto exit; |
if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) |
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; |
else |
ret = 0; |
exit: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
fclose( f ); |
return( ret ); |
} |
int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) |
{ |
int ret = 0; |
FILE *f = NULL; |
size_t n; |
unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; |
unsigned char c; |
if( ( f = fopen( path, "rb" ) ) == NULL ) |
return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); |
n = fread( buf, 1, sizeof( buf ), f ); |
if( fread( &c, 1, 1, f ) != 0 ) |
{ |
ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; |
goto exit; |
} |
if( n == 0 || ferror( f ) ) |
{ |
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; |
goto exit; |
} |
fclose( f ); |
f = NULL; |
ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); |
exit: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
if( f != NULL ) |
fclose( f ); |
if( ret != 0 ) |
return( ret ); |
return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); |
} |
#endif /* MBEDTLS_FS_IO */ |
#if defined(MBEDTLS_SELF_TEST) |
static const unsigned char entropy_source_pr[96] = |
{ 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, |
0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, |
0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, |
0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, |
0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, |
0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, |
0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, |
0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, |
0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, |
0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, |
0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, |
0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; |
static const unsigned char entropy_source_nopr[64] = |
{ 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, |
0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, |
0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, |
0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, |
0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, |
0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, |
0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, |
0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; |
static const unsigned char nonce_pers_pr[16] = |
{ 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, |
0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; |
static const unsigned char nonce_pers_nopr[16] = |
{ 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, |
0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; |
static const unsigned char result_pr[16] = |
{ 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, |
0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; |
static const unsigned char result_nopr[16] = |
{ 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, |
0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; |
static size_t test_offset; |
static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, |
size_t len ) |
{ |
const unsigned char *p = data; |
memcpy( buf, p + test_offset, len ); |
test_offset += len; |
return( 0 ); |
} |
#define CHK( c ) if( (c) != 0 ) \ |
{ \ |
if( verbose != 0 ) \ |
mbedtls_printf( "failed\n" ); \ |
return( 1 ); \ |
} |
/* |
* Checkup routine |
*/ |
int mbedtls_ctr_drbg_self_test( int verbose ) |
{ |
mbedtls_ctr_drbg_context ctx; |
unsigned char buf[16]; |
mbedtls_ctr_drbg_init( &ctx ); |
/* |
* Based on a NIST CTR_DRBG test vector (PR = True) |
*/ |
if( verbose != 0 ) |
mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); |
test_offset = 0; |
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); |
CHK( mbedtls_ctr_drbg_seed( &ctx, |
ctr_drbg_self_test_entropy, |
(void *) entropy_source_pr, |
nonce_pers_pr, 16 ) ); |
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); |
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); |
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); |
CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); |
mbedtls_ctr_drbg_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
/* |
* Based on a NIST CTR_DRBG test vector (PR = FALSE) |
*/ |
if( verbose != 0 ) |
mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); |
mbedtls_ctr_drbg_init( &ctx ); |
test_offset = 0; |
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); |
CHK( mbedtls_ctr_drbg_seed( &ctx, |
ctr_drbg_self_test_entropy, |
(void *) entropy_source_nopr, |
nonce_pers_nopr, 16 ) ); |
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); |
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); |
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); |
CHK( memcmp( buf, result_nopr, 16 ) ); |
mbedtls_ctr_drbg_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_CTR_DRBG_C */ |
/programs/develop/libraries/kos_mbedtls/library/debug.c |
---|
0,0 → 1,452 |
/* |
* Debugging routines |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_DEBUG_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#define mbedtls_time_t time_t |
#define mbedtls_snprintf snprintf |
#endif |
#include "mbedtls/debug.h" |
#include <stdarg.h> |
#include <stdio.h> |
#include <string.h> |
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ |
!defined(inline) && !defined(__cplusplus) |
#define inline __inline |
#endif |
#define DEBUG_BUF_SIZE 512 |
static int debug_threshold = 0; |
void mbedtls_debug_set_threshold( int threshold ) |
{ |
debug_threshold = threshold; |
} |
/* |
* All calls to f_dbg must be made via this function |
*/ |
static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const char *str ) |
{ |
/* |
* If in a threaded environment, we need a thread identifier. |
* Since there is no portable way to get one, use the address of the ssl |
* context instead, as it shouldn't be shared between threads. |
*/ |
#if defined(MBEDTLS_THREADING_C) |
char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ |
mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); |
ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); |
#else |
ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); |
#endif |
} |
void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const char *format, ... ) |
{ |
va_list argp; |
char str[DEBUG_BUF_SIZE]; |
int ret; |
if( NULL == ssl || |
NULL == ssl->conf || |
NULL == ssl->conf->f_dbg || |
level > debug_threshold ) |
{ |
return; |
} |
va_start( argp, format ); |
#if defined(_WIN32) |
#if defined(_TRUNCATE) && !defined(__MINGW32__) |
ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); |
#else |
ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); |
if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE ) |
{ |
str[DEBUG_BUF_SIZE-1] = '\0'; |
ret = -1; |
} |
#endif |
#else |
ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); |
#endif |
va_end( argp ); |
if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) |
{ |
str[ret] = '\n'; |
str[ret + 1] = '\0'; |
} |
debug_send_line( ssl, level, file, line, str ); |
} |
void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const char *text, int ret ) |
{ |
char str[DEBUG_BUF_SIZE]; |
if( NULL == ssl || |
NULL == ssl->conf || |
NULL == ssl->conf->f_dbg || |
level > debug_threshold ) |
{ |
return; |
} |
/* |
* With non-blocking I/O and examples that just retry immediately, |
* the logs would be quickly flooded with WANT_READ, so ignore that. |
* Don't ignore WANT_WRITE however, since is is usually rare. |
*/ |
if( ret == MBEDTLS_ERR_SSL_WANT_READ ) |
return; |
mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", |
text, ret, -ret ); |
debug_send_line( ssl, level, file, line, str ); |
} |
void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, const char *text, |
const unsigned char *buf, size_t len ) |
{ |
char str[DEBUG_BUF_SIZE]; |
char txt[17]; |
size_t i, idx = 0; |
if( NULL == ssl || |
NULL == ssl->conf || |
NULL == ssl->conf->f_dbg || |
level > debug_threshold ) |
{ |
return; |
} |
mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", |
text, (unsigned int) len ); |
debug_send_line( ssl, level, file, line, str ); |
idx = 0; |
memset( txt, 0, sizeof( txt ) ); |
for( i = 0; i < len; i++ ) |
{ |
if( i >= 4096 ) |
break; |
if( i % 16 == 0 ) |
{ |
if( i > 0 ) |
{ |
mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); |
debug_send_line( ssl, level, file, line, str ); |
idx = 0; |
memset( txt, 0, sizeof( txt ) ); |
} |
idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", |
(unsigned int) i ); |
} |
idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", |
(unsigned int) buf[i] ); |
txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; |
} |
if( len > 0 ) |
{ |
for( /* i = i */; i % 16 != 0; i++ ) |
idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); |
mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); |
debug_send_line( ssl, level, file, line, str ); |
} |
} |
#if defined(MBEDTLS_ECP_C) |
void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const char *text, const mbedtls_ecp_point *X ) |
{ |
char str[DEBUG_BUF_SIZE]; |
if( NULL == ssl || |
NULL == ssl->conf || |
NULL == ssl->conf->f_dbg || |
level > debug_threshold ) |
{ |
return; |
} |
mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); |
mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); |
mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); |
mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); |
} |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_BIGNUM_C) |
void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const char *text, const mbedtls_mpi *X ) |
{ |
char str[DEBUG_BUF_SIZE]; |
int j, k, zeros = 1; |
size_t i, n, idx = 0; |
if( NULL == ssl || |
NULL == ssl->conf || |
NULL == ssl->conf->f_dbg || |
NULL == X || |
level > debug_threshold ) |
{ |
return; |
} |
for( n = X->n - 1; n > 0; n-- ) |
if( X->p[n] != 0 ) |
break; |
for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) |
if( ( ( X->p[n] >> j ) & 1 ) != 0 ) |
break; |
mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", |
text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); |
debug_send_line( ssl, level, file, line, str ); |
idx = 0; |
for( i = n + 1, j = 0; i > 0; i-- ) |
{ |
if( zeros && X->p[i - 1] == 0 ) |
continue; |
for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) |
{ |
if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) |
continue; |
else |
zeros = 0; |
if( j % 16 == 0 ) |
{ |
if( j > 0 ) |
{ |
mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); |
debug_send_line( ssl, level, file, line, str ); |
idx = 0; |
} |
} |
idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) |
( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); |
j++; |
} |
} |
if( zeros == 1 ) |
idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); |
mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); |
debug_send_line( ssl, level, file, line, str ); |
} |
#endif /* MBEDTLS_BIGNUM_C */ |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const char *text, const mbedtls_pk_context *pk ) |
{ |
size_t i; |
mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; |
char name[16]; |
memset( items, 0, sizeof( items ) ); |
if( mbedtls_pk_debug( pk, items ) != 0 ) |
{ |
debug_send_line( ssl, level, file, line, |
"invalid PK context\n" ); |
return; |
} |
for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) |
{ |
if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) |
return; |
mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); |
name[sizeof( name ) - 1] = '\0'; |
if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) |
mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); |
else |
#if defined(MBEDTLS_ECP_C) |
if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) |
mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); |
else |
#endif |
debug_send_line( ssl, level, file, line, |
"should not happen\n" ); |
} |
} |
static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, const char *text ) |
{ |
char str[DEBUG_BUF_SIZE]; |
const char *start, *cur; |
start = text; |
for( cur = text; *cur != '\0'; cur++ ) |
{ |
if( *cur == '\n' ) |
{ |
size_t len = cur - start + 1; |
if( len > DEBUG_BUF_SIZE - 1 ) |
len = DEBUG_BUF_SIZE - 1; |
memcpy( str, start, len ); |
str[len] = '\0'; |
debug_send_line( ssl, level, file, line, str ); |
start = cur + 1; |
} |
} |
} |
void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const char *text, const mbedtls_x509_crt *crt ) |
{ |
char str[DEBUG_BUF_SIZE]; |
int i = 0; |
if( NULL == ssl || |
NULL == ssl->conf || |
NULL == ssl->conf->f_dbg || |
NULL == crt || |
level > debug_threshold ) |
{ |
return; |
} |
while( crt != NULL ) |
{ |
char buf[1024]; |
mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); |
debug_send_line( ssl, level, file, line, str ); |
mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); |
debug_print_line_by_line( ssl, level, file, line, buf ); |
debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); |
crt = crt->next; |
} |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
#if defined(MBEDTLS_ECDH_C) |
static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl, |
int level, const char *file, |
int line, |
const mbedtls_ecdh_context *ecdh, |
mbedtls_debug_ecdh_attr attr ) |
{ |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
const mbedtls_ecdh_context* ctx = ecdh; |
#else |
const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh; |
#endif |
switch( attr ) |
{ |
case MBEDTLS_DEBUG_ECDH_Q: |
mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q", |
&ctx->Q ); |
break; |
case MBEDTLS_DEBUG_ECDH_QP: |
mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp", |
&ctx->Qp ); |
break; |
case MBEDTLS_DEBUG_ECDH_Z: |
mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z", |
&ctx->z ); |
break; |
default: |
break; |
} |
} |
void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, |
const char *file, int line, |
const mbedtls_ecdh_context *ecdh, |
mbedtls_debug_ecdh_attr attr ) |
{ |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr ); |
#else |
switch( ecdh->var ) |
{ |
default: |
mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, |
attr ); |
} |
#endif |
} |
#endif /* MBEDTLS_ECDH_C */ |
#endif /* MBEDTLS_DEBUG_C */ |
/programs/develop/libraries/kos_mbedtls/library/des.c |
---|
0,0 → 1,1066 |
/* |
* FIPS-46-3 compliant Triple-DES implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* DES, on which TDES is based, was originally designed by Horst Feistel |
* at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). |
* |
* http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_DES_C) |
#include "mbedtls/des.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_DES_ALT) |
/* |
* 32-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} |
#endif |
/* |
* Expanded DES S-boxes |
*/ |
static const uint32_t SB1[64] = |
{ |
0x01010400, 0x00000000, 0x00010000, 0x01010404, |
0x01010004, 0x00010404, 0x00000004, 0x00010000, |
0x00000400, 0x01010400, 0x01010404, 0x00000400, |
0x01000404, 0x01010004, 0x01000000, 0x00000004, |
0x00000404, 0x01000400, 0x01000400, 0x00010400, |
0x00010400, 0x01010000, 0x01010000, 0x01000404, |
0x00010004, 0x01000004, 0x01000004, 0x00010004, |
0x00000000, 0x00000404, 0x00010404, 0x01000000, |
0x00010000, 0x01010404, 0x00000004, 0x01010000, |
0x01010400, 0x01000000, 0x01000000, 0x00000400, |
0x01010004, 0x00010000, 0x00010400, 0x01000004, |
0x00000400, 0x00000004, 0x01000404, 0x00010404, |
0x01010404, 0x00010004, 0x01010000, 0x01000404, |
0x01000004, 0x00000404, 0x00010404, 0x01010400, |
0x00000404, 0x01000400, 0x01000400, 0x00000000, |
0x00010004, 0x00010400, 0x00000000, 0x01010004 |
}; |
static const uint32_t SB2[64] = |
{ |
0x80108020, 0x80008000, 0x00008000, 0x00108020, |
0x00100000, 0x00000020, 0x80100020, 0x80008020, |
0x80000020, 0x80108020, 0x80108000, 0x80000000, |
0x80008000, 0x00100000, 0x00000020, 0x80100020, |
0x00108000, 0x00100020, 0x80008020, 0x00000000, |
0x80000000, 0x00008000, 0x00108020, 0x80100000, |
0x00100020, 0x80000020, 0x00000000, 0x00108000, |
0x00008020, 0x80108000, 0x80100000, 0x00008020, |
0x00000000, 0x00108020, 0x80100020, 0x00100000, |
0x80008020, 0x80100000, 0x80108000, 0x00008000, |
0x80100000, 0x80008000, 0x00000020, 0x80108020, |
0x00108020, 0x00000020, 0x00008000, 0x80000000, |
0x00008020, 0x80108000, 0x00100000, 0x80000020, |
0x00100020, 0x80008020, 0x80000020, 0x00100020, |
0x00108000, 0x00000000, 0x80008000, 0x00008020, |
0x80000000, 0x80100020, 0x80108020, 0x00108000 |
}; |
static const uint32_t SB3[64] = |
{ |
0x00000208, 0x08020200, 0x00000000, 0x08020008, |
0x08000200, 0x00000000, 0x00020208, 0x08000200, |
0x00020008, 0x08000008, 0x08000008, 0x00020000, |
0x08020208, 0x00020008, 0x08020000, 0x00000208, |
0x08000000, 0x00000008, 0x08020200, 0x00000200, |
0x00020200, 0x08020000, 0x08020008, 0x00020208, |
0x08000208, 0x00020200, 0x00020000, 0x08000208, |
0x00000008, 0x08020208, 0x00000200, 0x08000000, |
0x08020200, 0x08000000, 0x00020008, 0x00000208, |
0x00020000, 0x08020200, 0x08000200, 0x00000000, |
0x00000200, 0x00020008, 0x08020208, 0x08000200, |
0x08000008, 0x00000200, 0x00000000, 0x08020008, |
0x08000208, 0x00020000, 0x08000000, 0x08020208, |
0x00000008, 0x00020208, 0x00020200, 0x08000008, |
0x08020000, 0x08000208, 0x00000208, 0x08020000, |
0x00020208, 0x00000008, 0x08020008, 0x00020200 |
}; |
static const uint32_t SB4[64] = |
{ |
0x00802001, 0x00002081, 0x00002081, 0x00000080, |
0x00802080, 0x00800081, 0x00800001, 0x00002001, |
0x00000000, 0x00802000, 0x00802000, 0x00802081, |
0x00000081, 0x00000000, 0x00800080, 0x00800001, |
0x00000001, 0x00002000, 0x00800000, 0x00802001, |
0x00000080, 0x00800000, 0x00002001, 0x00002080, |
0x00800081, 0x00000001, 0x00002080, 0x00800080, |
0x00002000, 0x00802080, 0x00802081, 0x00000081, |
0x00800080, 0x00800001, 0x00802000, 0x00802081, |
0x00000081, 0x00000000, 0x00000000, 0x00802000, |
0x00002080, 0x00800080, 0x00800081, 0x00000001, |
0x00802001, 0x00002081, 0x00002081, 0x00000080, |
0x00802081, 0x00000081, 0x00000001, 0x00002000, |
0x00800001, 0x00002001, 0x00802080, 0x00800081, |
0x00002001, 0x00002080, 0x00800000, 0x00802001, |
0x00000080, 0x00800000, 0x00002000, 0x00802080 |
}; |
static const uint32_t SB5[64] = |
{ |
0x00000100, 0x02080100, 0x02080000, 0x42000100, |
0x00080000, 0x00000100, 0x40000000, 0x02080000, |
0x40080100, 0x00080000, 0x02000100, 0x40080100, |
0x42000100, 0x42080000, 0x00080100, 0x40000000, |
0x02000000, 0x40080000, 0x40080000, 0x00000000, |
0x40000100, 0x42080100, 0x42080100, 0x02000100, |
0x42080000, 0x40000100, 0x00000000, 0x42000000, |
0x02080100, 0x02000000, 0x42000000, 0x00080100, |
0x00080000, 0x42000100, 0x00000100, 0x02000000, |
0x40000000, 0x02080000, 0x42000100, 0x40080100, |
0x02000100, 0x40000000, 0x42080000, 0x02080100, |
0x40080100, 0x00000100, 0x02000000, 0x42080000, |
0x42080100, 0x00080100, 0x42000000, 0x42080100, |
0x02080000, 0x00000000, 0x40080000, 0x42000000, |
0x00080100, 0x02000100, 0x40000100, 0x00080000, |
0x00000000, 0x40080000, 0x02080100, 0x40000100 |
}; |
static const uint32_t SB6[64] = |
{ |
0x20000010, 0x20400000, 0x00004000, 0x20404010, |
0x20400000, 0x00000010, 0x20404010, 0x00400000, |
0x20004000, 0x00404010, 0x00400000, 0x20000010, |
0x00400010, 0x20004000, 0x20000000, 0x00004010, |
0x00000000, 0x00400010, 0x20004010, 0x00004000, |
0x00404000, 0x20004010, 0x00000010, 0x20400010, |
0x20400010, 0x00000000, 0x00404010, 0x20404000, |
0x00004010, 0x00404000, 0x20404000, 0x20000000, |
0x20004000, 0x00000010, 0x20400010, 0x00404000, |
0x20404010, 0x00400000, 0x00004010, 0x20000010, |
0x00400000, 0x20004000, 0x20000000, 0x00004010, |
0x20000010, 0x20404010, 0x00404000, 0x20400000, |
0x00404010, 0x20404000, 0x00000000, 0x20400010, |
0x00000010, 0x00004000, 0x20400000, 0x00404010, |
0x00004000, 0x00400010, 0x20004010, 0x00000000, |
0x20404000, 0x20000000, 0x00400010, 0x20004010 |
}; |
static const uint32_t SB7[64] = |
{ |
0x00200000, 0x04200002, 0x04000802, 0x00000000, |
0x00000800, 0x04000802, 0x00200802, 0x04200800, |
0x04200802, 0x00200000, 0x00000000, 0x04000002, |
0x00000002, 0x04000000, 0x04200002, 0x00000802, |
0x04000800, 0x00200802, 0x00200002, 0x04000800, |
0x04000002, 0x04200000, 0x04200800, 0x00200002, |
0x04200000, 0x00000800, 0x00000802, 0x04200802, |
0x00200800, 0x00000002, 0x04000000, 0x00200800, |
0x04000000, 0x00200800, 0x00200000, 0x04000802, |
0x04000802, 0x04200002, 0x04200002, 0x00000002, |
0x00200002, 0x04000000, 0x04000800, 0x00200000, |
0x04200800, 0x00000802, 0x00200802, 0x04200800, |
0x00000802, 0x04000002, 0x04200802, 0x04200000, |
0x00200800, 0x00000000, 0x00000002, 0x04200802, |
0x00000000, 0x00200802, 0x04200000, 0x00000800, |
0x04000002, 0x04000800, 0x00000800, 0x00200002 |
}; |
static const uint32_t SB8[64] = |
{ |
0x10001040, 0x00001000, 0x00040000, 0x10041040, |
0x10000000, 0x10001040, 0x00000040, 0x10000000, |
0x00040040, 0x10040000, 0x10041040, 0x00041000, |
0x10041000, 0x00041040, 0x00001000, 0x00000040, |
0x10040000, 0x10000040, 0x10001000, 0x00001040, |
0x00041000, 0x00040040, 0x10040040, 0x10041000, |
0x00001040, 0x00000000, 0x00000000, 0x10040040, |
0x10000040, 0x10001000, 0x00041040, 0x00040000, |
0x00041040, 0x00040000, 0x10041000, 0x00001000, |
0x00000040, 0x10040040, 0x00001000, 0x00041040, |
0x10001000, 0x00000040, 0x10000040, 0x10040000, |
0x10040040, 0x10000000, 0x00040000, 0x10001040, |
0x00000000, 0x10041040, 0x00040040, 0x10000040, |
0x10040000, 0x10001000, 0x10001040, 0x00000000, |
0x10041040, 0x00041000, 0x00041000, 0x00001040, |
0x00001040, 0x00040040, 0x10000000, 0x10041000 |
}; |
/* |
* PC1: left and right halves bit-swap |
*/ |
static const uint32_t LHs[16] = |
{ |
0x00000000, 0x00000001, 0x00000100, 0x00000101, |
0x00010000, 0x00010001, 0x00010100, 0x00010101, |
0x01000000, 0x01000001, 0x01000100, 0x01000101, |
0x01010000, 0x01010001, 0x01010100, 0x01010101 |
}; |
static const uint32_t RHs[16] = |
{ |
0x00000000, 0x01000000, 0x00010000, 0x01010000, |
0x00000100, 0x01000100, 0x00010100, 0x01010100, |
0x00000001, 0x01000001, 0x00010001, 0x01010001, |
0x00000101, 0x01000101, 0x00010101, 0x01010101, |
}; |
/* |
* Initial Permutation macro |
*/ |
#define DES_IP(X,Y) \ |
do \ |
{ \ |
T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ |
T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ |
T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ |
T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ |
(Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF; \ |
T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T; \ |
(X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF; \ |
} while( 0 ) |
/* |
* Final Permutation macro |
*/ |
#define DES_FP(X,Y) \ |
do \ |
{ \ |
(X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF; \ |
T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T; \ |
(Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF; \ |
T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ |
T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ |
T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ |
T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ |
} while( 0 ) |
/* |
* DES round macro |
*/ |
#define DES_ROUND(X,Y) \ |
do \ |
{ \ |
T = *SK++ ^ (X); \ |
(Y) ^= SB8[ (T ) & 0x3F ] ^ \ |
SB6[ (T >> 8) & 0x3F ] ^ \ |
SB4[ (T >> 16) & 0x3F ] ^ \ |
SB2[ (T >> 24) & 0x3F ]; \ |
\ |
T = *SK++ ^ (((X) << 28) | ((X) >> 4)); \ |
(Y) ^= SB7[ (T ) & 0x3F ] ^ \ |
SB5[ (T >> 8) & 0x3F ] ^ \ |
SB3[ (T >> 16) & 0x3F ] ^ \ |
SB1[ (T >> 24) & 0x3F ]; \ |
} while( 0 ) |
#define SWAP(a,b) \ |
do \ |
{ \ |
uint32_t t = (a); (a) = (b); (b) = t; t = 0; \ |
} while( 0 ) |
void mbedtls_des_init( mbedtls_des_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_des_context ) ); |
} |
void mbedtls_des_free( mbedtls_des_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); |
} |
void mbedtls_des3_init( mbedtls_des3_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_des3_context ) ); |
} |
void mbedtls_des3_free( mbedtls_des3_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); |
} |
static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, |
11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, |
47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, |
82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, |
115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, |
143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, |
171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, |
199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, |
227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, |
254 }; |
void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) |
{ |
int i; |
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) |
key[i] = odd_parity_table[key[i] / 2]; |
} |
/* |
* Check the given key's parity, returns 1 on failure, 0 on SUCCESS |
*/ |
int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) |
{ |
int i; |
for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) |
if( key[i] != odd_parity_table[key[i] / 2] ) |
return( 1 ); |
return( 0 ); |
} |
/* |
* Table of weak and semi-weak keys |
* |
* Source: http://en.wikipedia.org/wiki/Weak_key |
* |
* Weak: |
* Alternating ones + zeros (0x0101010101010101) |
* Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) |
* '0xE0E0E0E0F1F1F1F1' |
* '0x1F1F1F1F0E0E0E0E' |
* |
* Semi-weak: |
* 0x011F011F010E010E and 0x1F011F010E010E01 |
* 0x01E001E001F101F1 and 0xE001E001F101F101 |
* 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 |
* 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E |
* 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E |
* 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 |
* |
*/ |
#define WEAK_KEY_COUNT 16 |
static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = |
{ |
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, |
{ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, |
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, |
{ 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, |
{ 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, |
{ 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, |
{ 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, |
{ 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, |
{ 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, |
{ 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, |
{ 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, |
{ 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, |
{ 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, |
{ 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, |
{ 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, |
{ 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } |
}; |
int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) |
{ |
int i; |
for( i = 0; i < WEAK_KEY_COUNT; i++ ) |
if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) |
return( 1 ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DES_SETKEY_ALT) |
void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) |
{ |
int i; |
uint32_t X, Y, T; |
GET_UINT32_BE( X, key, 0 ); |
GET_UINT32_BE( Y, key, 4 ); |
/* |
* Permuted Choice 1 |
*/ |
T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); |
T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); |
X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) |
| (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) |
| (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) |
| (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); |
Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) |
| (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) |
| (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) |
| (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); |
X &= 0x0FFFFFFF; |
Y &= 0x0FFFFFFF; |
/* |
* calculate subkeys |
*/ |
for( i = 0; i < 16; i++ ) |
{ |
if( i < 2 || i == 8 || i == 15 ) |
{ |
X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; |
Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; |
} |
else |
{ |
X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; |
Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; |
} |
*SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) |
| ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) |
| ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) |
| ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) |
| ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) |
| ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) |
| ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) |
| ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) |
| ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) |
| ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) |
| ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); |
*SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) |
| ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) |
| ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) |
| ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) |
| ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) |
| ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) |
| ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) |
| ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) |
| ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) |
| ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) |
| ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); |
} |
} |
#endif /* !MBEDTLS_DES_SETKEY_ALT */ |
/* |
* DES key schedule (56-bit, encryption) |
*/ |
int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) |
{ |
mbedtls_des_setkey( ctx->sk, key ); |
return( 0 ); |
} |
/* |
* DES key schedule (56-bit, decryption) |
*/ |
int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) |
{ |
int i; |
mbedtls_des_setkey( ctx->sk, key ); |
for( i = 0; i < 16; i += 2 ) |
{ |
SWAP( ctx->sk[i ], ctx->sk[30 - i] ); |
SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); |
} |
return( 0 ); |
} |
static void des3_set2key( uint32_t esk[96], |
uint32_t dsk[96], |
const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) |
{ |
int i; |
mbedtls_des_setkey( esk, key ); |
mbedtls_des_setkey( dsk + 32, key + 8 ); |
for( i = 0; i < 32; i += 2 ) |
{ |
dsk[i ] = esk[30 - i]; |
dsk[i + 1] = esk[31 - i]; |
esk[i + 32] = dsk[62 - i]; |
esk[i + 33] = dsk[63 - i]; |
esk[i + 64] = esk[i ]; |
esk[i + 65] = esk[i + 1]; |
dsk[i + 64] = dsk[i ]; |
dsk[i + 65] = dsk[i + 1]; |
} |
} |
/* |
* Triple-DES key schedule (112-bit, encryption) |
*/ |
int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, |
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) |
{ |
uint32_t sk[96]; |
des3_set2key( ctx->sk, sk, key ); |
mbedtls_platform_zeroize( sk, sizeof( sk ) ); |
return( 0 ); |
} |
/* |
* Triple-DES key schedule (112-bit, decryption) |
*/ |
int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, |
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) |
{ |
uint32_t sk[96]; |
des3_set2key( sk, ctx->sk, key ); |
mbedtls_platform_zeroize( sk, sizeof( sk ) ); |
return( 0 ); |
} |
static void des3_set3key( uint32_t esk[96], |
uint32_t dsk[96], |
const unsigned char key[24] ) |
{ |
int i; |
mbedtls_des_setkey( esk, key ); |
mbedtls_des_setkey( dsk + 32, key + 8 ); |
mbedtls_des_setkey( esk + 64, key + 16 ); |
for( i = 0; i < 32; i += 2 ) |
{ |
dsk[i ] = esk[94 - i]; |
dsk[i + 1] = esk[95 - i]; |
esk[i + 32] = dsk[62 - i]; |
esk[i + 33] = dsk[63 - i]; |
dsk[i + 64] = esk[30 - i]; |
dsk[i + 65] = esk[31 - i]; |
} |
} |
/* |
* Triple-DES key schedule (168-bit, encryption) |
*/ |
int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, |
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) |
{ |
uint32_t sk[96]; |
des3_set3key( ctx->sk, sk, key ); |
mbedtls_platform_zeroize( sk, sizeof( sk ) ); |
return( 0 ); |
} |
/* |
* Triple-DES key schedule (168-bit, decryption) |
*/ |
int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, |
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) |
{ |
uint32_t sk[96]; |
des3_set3key( sk, ctx->sk, key ); |
mbedtls_platform_zeroize( sk, sizeof( sk ) ); |
return( 0 ); |
} |
/* |
* DES-ECB block encryption/decryption |
*/ |
#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) |
int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, |
const unsigned char input[8], |
unsigned char output[8] ) |
{ |
int i; |
uint32_t X, Y, T, *SK; |
SK = ctx->sk; |
GET_UINT32_BE( X, input, 0 ); |
GET_UINT32_BE( Y, input, 4 ); |
DES_IP( X, Y ); |
for( i = 0; i < 8; i++ ) |
{ |
DES_ROUND( Y, X ); |
DES_ROUND( X, Y ); |
} |
DES_FP( Y, X ); |
PUT_UINT32_BE( Y, output, 0 ); |
PUT_UINT32_BE( X, output, 4 ); |
return( 0 ); |
} |
#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* DES-CBC buffer encryption/decryption |
*/ |
int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[8], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int i; |
unsigned char temp[8]; |
if( length % 8 ) |
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); |
if( mode == MBEDTLS_DES_ENCRYPT ) |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < 8; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
mbedtls_des_crypt_ecb( ctx, output, output ); |
memcpy( iv, output, 8 ); |
input += 8; |
output += 8; |
length -= 8; |
} |
} |
else /* MBEDTLS_DES_DECRYPT */ |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, 8 ); |
mbedtls_des_crypt_ecb( ctx, input, output ); |
for( i = 0; i < 8; i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, 8 ); |
input += 8; |
output += 8; |
length -= 8; |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
/* |
* 3DES-ECB block encryption/decryption |
*/ |
#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) |
int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, |
const unsigned char input[8], |
unsigned char output[8] ) |
{ |
int i; |
uint32_t X, Y, T, *SK; |
SK = ctx->sk; |
GET_UINT32_BE( X, input, 0 ); |
GET_UINT32_BE( Y, input, 4 ); |
DES_IP( X, Y ); |
for( i = 0; i < 8; i++ ) |
{ |
DES_ROUND( Y, X ); |
DES_ROUND( X, Y ); |
} |
for( i = 0; i < 8; i++ ) |
{ |
DES_ROUND( X, Y ); |
DES_ROUND( Y, X ); |
} |
for( i = 0; i < 8; i++ ) |
{ |
DES_ROUND( Y, X ); |
DES_ROUND( X, Y ); |
} |
DES_FP( Y, X ); |
PUT_UINT32_BE( Y, output, 0 ); |
PUT_UINT32_BE( X, output, 4 ); |
return( 0 ); |
} |
#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* 3DES-CBC buffer encryption/decryption |
*/ |
int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[8], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int i; |
unsigned char temp[8]; |
if( length % 8 ) |
return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); |
if( mode == MBEDTLS_DES_ENCRYPT ) |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < 8; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
mbedtls_des3_crypt_ecb( ctx, output, output ); |
memcpy( iv, output, 8 ); |
input += 8; |
output += 8; |
length -= 8; |
} |
} |
else /* MBEDTLS_DES_DECRYPT */ |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, 8 ); |
mbedtls_des3_crypt_ecb( ctx, input, output ); |
for( i = 0; i < 8; i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, 8 ); |
input += 8; |
output += 8; |
length -= 8; |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* !MBEDTLS_DES_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* DES and 3DES test vectors from: |
* |
* http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip |
*/ |
static const unsigned char des3_test_keys[24] = |
{ |
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, |
0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, |
0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 |
}; |
static const unsigned char des3_test_buf[8] = |
{ |
0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 |
}; |
static const unsigned char des3_test_ecb_dec[3][8] = |
{ |
{ 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, |
{ 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, |
{ 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } |
}; |
static const unsigned char des3_test_ecb_enc[3][8] = |
{ |
{ 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, |
{ 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, |
{ 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } |
}; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
static const unsigned char des3_test_iv[8] = |
{ |
0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, |
}; |
static const unsigned char des3_test_cbc_dec[3][8] = |
{ |
{ 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, |
{ 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, |
{ 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } |
}; |
static const unsigned char des3_test_cbc_enc[3][8] = |
{ |
{ 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, |
{ 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, |
{ 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } |
}; |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
/* |
* Checkup routine |
*/ |
int mbedtls_des_self_test( int verbose ) |
{ |
int i, j, u, v, ret = 0; |
mbedtls_des_context ctx; |
mbedtls_des3_context ctx3; |
unsigned char buf[8]; |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
unsigned char prv[8]; |
unsigned char iv[8]; |
#endif |
mbedtls_des_init( &ctx ); |
mbedtls_des3_init( &ctx3 ); |
/* |
* ECB mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
v = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " DES%c-ECB-%3d (%s): ", |
( u == 0 ) ? ' ' : '3', 56 + u * 56, |
( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); |
memcpy( buf, des3_test_buf, 8 ); |
switch( i ) |
{ |
case 0: |
mbedtls_des_setkey_dec( &ctx, des3_test_keys ); |
break; |
case 1: |
mbedtls_des_setkey_enc( &ctx, des3_test_keys ); |
break; |
case 2: |
mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); |
break; |
case 3: |
mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); |
break; |
case 4: |
mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); |
break; |
case 5: |
mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); |
break; |
default: |
return( 1 ); |
} |
for( j = 0; j < 10000; j++ ) |
{ |
if( u == 0 ) |
mbedtls_des_crypt_ecb( &ctx, buf, buf ); |
else |
mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); |
} |
if( ( v == MBEDTLS_DES_DECRYPT && |
memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || |
( v != MBEDTLS_DES_DECRYPT && |
memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* CBC mode |
*/ |
for( i = 0; i < 6; i++ ) |
{ |
u = i >> 1; |
v = i & 1; |
if( verbose != 0 ) |
mbedtls_printf( " DES%c-CBC-%3d (%s): ", |
( u == 0 ) ? ' ' : '3', 56 + u * 56, |
( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); |
memcpy( iv, des3_test_iv, 8 ); |
memcpy( prv, des3_test_iv, 8 ); |
memcpy( buf, des3_test_buf, 8 ); |
switch( i ) |
{ |
case 0: |
mbedtls_des_setkey_dec( &ctx, des3_test_keys ); |
break; |
case 1: |
mbedtls_des_setkey_enc( &ctx, des3_test_keys ); |
break; |
case 2: |
mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); |
break; |
case 3: |
mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); |
break; |
case 4: |
mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); |
break; |
case 5: |
mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); |
break; |
default: |
return( 1 ); |
} |
if( v == MBEDTLS_DES_DECRYPT ) |
{ |
for( j = 0; j < 10000; j++ ) |
{ |
if( u == 0 ) |
mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); |
else |
mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); |
} |
} |
else |
{ |
for( j = 0; j < 10000; j++ ) |
{ |
unsigned char tmp[8]; |
if( u == 0 ) |
mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); |
else |
mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); |
memcpy( tmp, prv, 8 ); |
memcpy( prv, buf, 8 ); |
memcpy( buf, tmp, 8 ); |
} |
memcpy( buf, prv, 8 ); |
} |
if( ( v == MBEDTLS_DES_DECRYPT && |
memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || |
( v != MBEDTLS_DES_DECRYPT && |
memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
exit: |
mbedtls_des_free( &ctx ); |
mbedtls_des3_free( &ctx3 ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_DES_C */ |
/programs/develop/libraries/kos_mbedtls/library/dhm.c |
---|
0,0 → 1,714 |
/* |
* Diffie-Hellman-Merkle key exchange |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The following sources were referenced in the design of this implementation |
* of the Diffie-Hellman-Merkle algorithm: |
* |
* [1] Handbook of Applied Cryptography - 1997, Chapter 12 |
* Menezes, van Oorschot and Vanstone |
* |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_DHM_C) |
#include "mbedtls/dhm.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PEM_PARSE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_ASN1_PARSE_C) |
#include "mbedtls/asn1.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#include <stdio.h> |
#define mbedtls_printf printf |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#if !defined(MBEDTLS_DHM_ALT) |
#define DHM_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) |
#define DHM_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* helper to validate the mbedtls_mpi size and import it |
*/ |
static int dhm_read_bignum( mbedtls_mpi *X, |
unsigned char **p, |
const unsigned char *end ) |
{ |
int ret, n; |
if( end - *p < 2 ) |
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); |
n = ( (*p)[0] << 8 ) | (*p)[1]; |
(*p) += 2; |
if( (int)( end - *p ) < n ) |
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); |
if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) |
return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); |
(*p) += n; |
return( 0 ); |
} |
/* |
* Verify sanity of parameter with regards to P |
* |
* Parameter should be: 2 <= public_param <= P - 2 |
* |
* This means that we need to return an error if |
* public_param < 2 or public_param > P-2 |
* |
* For more information on the attack, see: |
* http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf |
* http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 |
*/ |
static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) |
{ |
mbedtls_mpi L, U; |
int ret = 0; |
mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); |
if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || |
mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) |
{ |
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; |
} |
cleanup: |
mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); |
return( ret ); |
} |
void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) |
{ |
DHM_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); |
} |
/* |
* Parse the ServerKeyExchange parameters |
*/ |
int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, |
unsigned char **p, |
const unsigned char *end ) |
{ |
int ret; |
DHM_VALIDATE_RET( ctx != NULL ); |
DHM_VALIDATE_RET( p != NULL && *p != NULL ); |
DHM_VALIDATE_RET( end != NULL ); |
if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || |
( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || |
( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) |
return( ret ); |
if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) |
return( ret ); |
ctx->len = mbedtls_mpi_size( &ctx->P ); |
return( 0 ); |
} |
/* |
* Setup and write the ServerKeyExchange parameters |
*/ |
int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, |
unsigned char *output, size_t *olen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret, count = 0; |
size_t n1, n2, n3; |
unsigned char *p; |
DHM_VALIDATE_RET( ctx != NULL ); |
DHM_VALIDATE_RET( output != NULL ); |
DHM_VALIDATE_RET( olen != NULL ); |
DHM_VALIDATE_RET( f_rng != NULL ); |
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) |
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); |
/* |
* Generate X as large as possible ( < P ) |
*/ |
do |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); |
while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); |
if( count++ > 10 ) |
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); |
} |
while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); |
/* |
* Calculate GX = G^X mod P |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, |
&ctx->P , &ctx->RP ) ); |
if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) |
return( ret ); |
/* |
* export P, G, GX |
*/ |
#define DHM_MPI_EXPORT( X, n ) \ |
do { \ |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ |
p + 2, \ |
( n ) ) ); \ |
*p++ = (unsigned char)( ( n ) >> 8 ); \ |
*p++ = (unsigned char)( ( n ) ); \ |
p += ( n ); \ |
} while( 0 ) |
n1 = mbedtls_mpi_size( &ctx->P ); |
n2 = mbedtls_mpi_size( &ctx->G ); |
n3 = mbedtls_mpi_size( &ctx->GX ); |
p = output; |
DHM_MPI_EXPORT( &ctx->P , n1 ); |
DHM_MPI_EXPORT( &ctx->G , n2 ); |
DHM_MPI_EXPORT( &ctx->GX, n3 ); |
*olen = p - output; |
ctx->len = n1; |
cleanup: |
if( ret != 0 ) |
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); |
return( 0 ); |
} |
/* |
* Set prime modulus and generator |
*/ |
int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, |
const mbedtls_mpi *P, |
const mbedtls_mpi *G ) |
{ |
int ret; |
DHM_VALIDATE_RET( ctx != NULL ); |
DHM_VALIDATE_RET( P != NULL ); |
DHM_VALIDATE_RET( G != NULL ); |
if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || |
( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); |
} |
ctx->len = mbedtls_mpi_size( &ctx->P ); |
return( 0 ); |
} |
/* |
* Import the peer's public value G^Y |
*/ |
int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, |
const unsigned char *input, size_t ilen ) |
{ |
int ret; |
DHM_VALIDATE_RET( ctx != NULL ); |
DHM_VALIDATE_RET( input != NULL ); |
if( ilen < 1 || ilen > ctx->len ) |
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); |
if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) |
return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); |
return( 0 ); |
} |
/* |
* Create own private value X and export G^X |
*/ |
int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, |
unsigned char *output, size_t olen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret, count = 0; |
DHM_VALIDATE_RET( ctx != NULL ); |
DHM_VALIDATE_RET( output != NULL ); |
DHM_VALIDATE_RET( f_rng != NULL ); |
if( olen < 1 || olen > ctx->len ) |
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); |
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) |
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); |
/* |
* generate X and calculate GX = G^X mod P |
*/ |
do |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); |
while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); |
if( count++ > 10 ) |
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); |
} |
while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, |
&ctx->P , &ctx->RP ) ); |
if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) |
return( ret ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); |
cleanup: |
if( ret != 0 ) |
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); |
return( 0 ); |
} |
/* |
* Use the blinding method and optimisation suggested in section 10 of: |
* KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, |
* DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer |
* Berlin Heidelberg, 1996. p. 104-113. |
*/ |
static int dhm_update_blinding( mbedtls_dhm_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
int ret, count; |
/* |
* Don't use any blinding the first time a particular X is used, |
* but remember it to use blinding next time. |
*/ |
if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); |
return( 0 ); |
} |
/* |
* Ok, we need blinding. Can we re-use existing values? |
* If yes, just update them by squaring them. |
*/ |
if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); |
return( 0 ); |
} |
/* |
* We need to generate blinding values from scratch |
*/ |
/* Vi = random( 2, P-1 ) */ |
count = 0; |
do |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); |
while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); |
if( count++ > 10 ) |
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); |
} |
while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); |
/* Vf = Vi^-X mod P */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Derive and export the shared secret (G^Y)^X mod P |
*/ |
int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, |
unsigned char *output, size_t output_size, size_t *olen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
mbedtls_mpi GYb; |
DHM_VALIDATE_RET( ctx != NULL ); |
DHM_VALIDATE_RET( output != NULL ); |
DHM_VALIDATE_RET( olen != NULL ); |
if( output_size < ctx->len ) |
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); |
if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) |
return( ret ); |
mbedtls_mpi_init( &GYb ); |
/* Blind peer's value */ |
if( f_rng != NULL ) |
{ |
MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); |
} |
else |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); |
/* Do modular exponentiation */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, |
&ctx->P, &ctx->RP ) ); |
/* Unblind secret value */ |
if( f_rng != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); |
} |
*olen = mbedtls_mpi_size( &ctx->K ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); |
cleanup: |
mbedtls_mpi_free( &GYb ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); |
return( 0 ); |
} |
/* |
* Free the components of a DHM key |
*/ |
void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_mpi_free( &ctx->pX ); |
mbedtls_mpi_free( &ctx->Vf ); |
mbedtls_mpi_free( &ctx->Vi ); |
mbedtls_mpi_free( &ctx->RP ); |
mbedtls_mpi_free( &ctx->K ); |
mbedtls_mpi_free( &ctx->GY ); |
mbedtls_mpi_free( &ctx->GX ); |
mbedtls_mpi_free( &ctx->X ); |
mbedtls_mpi_free( &ctx->G ); |
mbedtls_mpi_free( &ctx->P ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); |
} |
#if defined(MBEDTLS_ASN1_PARSE_C) |
/* |
* Parse DHM parameters |
*/ |
int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, |
size_t dhminlen ) |
{ |
int ret; |
size_t len; |
unsigned char *p, *end; |
#if defined(MBEDTLS_PEM_PARSE_C) |
mbedtls_pem_context pem; |
#endif /* MBEDTLS_PEM_PARSE_C */ |
DHM_VALIDATE_RET( dhm != NULL ); |
DHM_VALIDATE_RET( dhmin != NULL ); |
#if defined(MBEDTLS_PEM_PARSE_C) |
mbedtls_pem_init( &pem ); |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN DH PARAMETERS-----", |
"-----END DH PARAMETERS-----", |
dhmin, NULL, 0, &dhminlen ); |
if( ret == 0 ) |
{ |
/* |
* Was PEM encoded |
*/ |
dhminlen = pem.buflen; |
} |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
goto exit; |
p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; |
#else |
p = (unsigned char *) dhmin; |
#endif /* MBEDTLS_PEM_PARSE_C */ |
end = p + dhminlen; |
/* |
* DHParams ::= SEQUENCE { |
* prime INTEGER, -- P |
* generator INTEGER, -- g |
* privateValueLength INTEGER OPTIONAL |
* } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; |
goto exit; |
} |
end = p + len; |
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || |
( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) |
{ |
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; |
goto exit; |
} |
if( p != end ) |
{ |
/* This might be the optional privateValueLength. |
* If so, we can cleanly discard it */ |
mbedtls_mpi rec; |
mbedtls_mpi_init( &rec ); |
ret = mbedtls_asn1_get_mpi( &p, end, &rec ); |
mbedtls_mpi_free( &rec ); |
if ( ret != 0 ) |
{ |
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; |
goto exit; |
} |
if ( p != end ) |
{ |
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; |
goto exit; |
} |
} |
ret = 0; |
dhm->len = mbedtls_mpi_size( &dhm->P ); |
exit: |
#if defined(MBEDTLS_PEM_PARSE_C) |
mbedtls_pem_free( &pem ); |
#endif |
if( ret != 0 ) |
mbedtls_dhm_free( dhm ); |
return( ret ); |
} |
#if defined(MBEDTLS_FS_IO) |
/* |
* Load all data from a file into a given buffer. |
* |
* The file is expected to contain either PEM or DER encoded data. |
* A terminating null byte is always appended. It is included in the announced |
* length only if the data looks like it is PEM encoded. |
*/ |
static int load_file( const char *path, unsigned char **buf, size_t *n ) |
{ |
FILE *f; |
long size; |
if( ( f = fopen( path, "rb" ) ) == NULL ) |
return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); |
fseek( f, 0, SEEK_END ); |
if( ( size = ftell( f ) ) == -1 ) |
{ |
fclose( f ); |
return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); |
} |
fseek( f, 0, SEEK_SET ); |
*n = (size_t) size; |
if( *n + 1 == 0 || |
( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) |
{ |
fclose( f ); |
return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); |
} |
if( fread( *buf, 1, *n, f ) != *n ) |
{ |
fclose( f ); |
mbedtls_platform_zeroize( *buf, *n + 1 ); |
mbedtls_free( *buf ); |
return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); |
} |
fclose( f ); |
(*buf)[*n] = '\0'; |
if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) |
++*n; |
return( 0 ); |
} |
/* |
* Load and parse DHM parameters |
*/ |
int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) |
{ |
int ret; |
size_t n; |
unsigned char *buf; |
DHM_VALIDATE_RET( dhm != NULL ); |
DHM_VALIDATE_RET( path != NULL ); |
if( ( ret = load_file( path, &buf, &n ) ) != 0 ) |
return( ret ); |
ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); |
mbedtls_platform_zeroize( buf, n ); |
mbedtls_free( buf ); |
return( ret ); |
} |
#endif /* MBEDTLS_FS_IO */ |
#endif /* MBEDTLS_ASN1_PARSE_C */ |
#endif /* MBEDTLS_DHM_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PEM_PARSE_C) |
static const char mbedtls_test_dhm_params[] = |
"-----BEGIN DH PARAMETERS-----\r\n" |
"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" |
"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" |
"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" |
"-----END DH PARAMETERS-----\r\n"; |
#else /* MBEDTLS_PEM_PARSE_C */ |
static const char mbedtls_test_dhm_params[] = { |
0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, |
0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, |
0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, |
0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, |
0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, |
0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, |
0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, |
0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, |
0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, |
0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, |
0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, |
0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; |
#endif /* MBEDTLS_PEM_PARSE_C */ |
static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); |
/* |
* Checkup routine |
*/ |
int mbedtls_dhm_self_test( int verbose ) |
{ |
int ret; |
mbedtls_dhm_context dhm; |
mbedtls_dhm_init( &dhm ); |
if( verbose != 0 ) |
mbedtls_printf( " DHM parameter load: " ); |
if( ( ret = mbedtls_dhm_parse_dhm( &dhm, |
(const unsigned char *) mbedtls_test_dhm_params, |
mbedtls_test_dhm_params_len ) ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n\n" ); |
exit: |
mbedtls_dhm_free( &dhm ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_DHM_C */ |
/programs/develop/libraries/kos_mbedtls/library/ecdh.c |
---|
0,0 → 1,678 |
/* |
* Elliptic curve Diffie-Hellman |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* References: |
* |
* SEC1 http://www.secg.org/index.php?action=secg,docs_secg |
* RFC 4492 |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ECDH_C) |
#include "mbedtls/ecdh.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
/* Parameter validation macros based on platform_util.h */ |
#define ECDH_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) |
#define ECDH_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; |
#endif |
static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( |
const mbedtls_ecdh_context *ctx ) |
{ |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ctx->grp.id ); |
#else |
return( ctx->grp_id ); |
#endif |
} |
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) |
/* |
* Generate public key (restartable version) |
* |
* Note: this internal function relies on its caller preserving the value of |
* the output parameter 'd' across continuation calls. This would not be |
* acceptable for a public function but is OK here as we control call sites. |
*/ |
static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, |
mbedtls_mpi *d, mbedtls_ecp_point *Q, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
/* If multiplication is in progress, we already generated a privkey */ |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx == NULL || rs_ctx->rsm == NULL ) |
#endif |
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, |
f_rng, p_rng, rs_ctx ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Generate public key |
*/ |
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
ECDH_VALIDATE_RET( grp != NULL ); |
ECDH_VALIDATE_RET( d != NULL ); |
ECDH_VALIDATE_RET( Q != NULL ); |
ECDH_VALIDATE_RET( f_rng != NULL ); |
return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); |
} |
#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ |
#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) |
/* |
* Compute shared secret (SEC1 3.3.1) |
*/ |
static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, |
mbedtls_mpi *z, |
const mbedtls_ecp_point *Q, const mbedtls_mpi *d, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_ecp_point P; |
mbedtls_ecp_point_init( &P ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, |
f_rng, p_rng, rs_ctx ) ); |
if( mbedtls_ecp_is_zero( &P ) ) |
{ |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); |
cleanup: |
mbedtls_ecp_point_free( &P ); |
return( ret ); |
} |
/* |
* Compute shared secret (SEC1 3.3.1) |
*/ |
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, |
const mbedtls_ecp_point *Q, const mbedtls_mpi *d, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
ECDH_VALIDATE_RET( grp != NULL ); |
ECDH_VALIDATE_RET( Q != NULL ); |
ECDH_VALIDATE_RET( d != NULL ); |
ECDH_VALIDATE_RET( z != NULL ); |
return( ecdh_compute_shared_restartable( grp, z, Q, d, |
f_rng, p_rng, NULL ) ); |
} |
#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ |
static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) |
{ |
mbedtls_ecp_group_init( &ctx->grp ); |
mbedtls_mpi_init( &ctx->d ); |
mbedtls_ecp_point_init( &ctx->Q ); |
mbedtls_ecp_point_init( &ctx->Qp ); |
mbedtls_mpi_init( &ctx->z ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
mbedtls_ecp_restart_init( &ctx->rs ); |
#endif |
} |
/* |
* Initialize context |
*/ |
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) |
{ |
ECDH_VALIDATE( ctx != NULL ); |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
ecdh_init_internal( ctx ); |
mbedtls_ecp_point_init( &ctx->Vi ); |
mbedtls_ecp_point_init( &ctx->Vf ); |
mbedtls_mpi_init( &ctx->_d ); |
#else |
memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); |
ctx->var = MBEDTLS_ECDH_VARIANT_NONE; |
#endif |
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
ctx->restart_enabled = 0; |
#endif |
} |
static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, |
mbedtls_ecp_group_id grp_id ) |
{ |
int ret; |
ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); |
if( ret != 0 ) |
{ |
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); |
} |
return( 0 ); |
} |
/* |
* Setup context |
*/ |
int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) |
{ |
ECDH_VALIDATE_RET( ctx != NULL ); |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ecdh_setup_internal( ctx, grp_id ) ); |
#else |
switch( grp_id ) |
{ |
default: |
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; |
ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; |
ctx->grp_id = grp_id; |
ecdh_init_internal( &ctx->ctx.mbed_ecdh ); |
return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); |
} |
#endif |
} |
static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) |
{ |
mbedtls_ecp_group_free( &ctx->grp ); |
mbedtls_mpi_free( &ctx->d ); |
mbedtls_ecp_point_free( &ctx->Q ); |
mbedtls_ecp_point_free( &ctx->Qp ); |
mbedtls_mpi_free( &ctx->z ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
mbedtls_ecp_restart_free( &ctx->rs ); |
#endif |
} |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* Enable restartable operations for context |
*/ |
void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) |
{ |
ECDH_VALIDATE( ctx != NULL ); |
ctx->restart_enabled = 1; |
} |
#endif |
/* |
* Free context |
*/ |
void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
mbedtls_ecp_point_free( &ctx->Vi ); |
mbedtls_ecp_point_free( &ctx->Vf ); |
mbedtls_mpi_free( &ctx->_d ); |
ecdh_free_internal( ctx ); |
#else |
switch( ctx->var ) |
{ |
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: |
ecdh_free_internal( &ctx->ctx.mbed_ecdh ); |
break; |
default: |
break; |
} |
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; |
ctx->var = MBEDTLS_ECDH_VARIANT_NONE; |
ctx->grp_id = MBEDTLS_ECP_DP_NONE; |
#endif |
} |
static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, |
size_t *olen, int point_format, |
unsigned char *buf, size_t blen, |
int (*f_rng)(void *, |
unsigned char *, |
size_t), |
void *p_rng, |
int restart_enabled ) |
{ |
int ret; |
size_t grp_len, pt_len; |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
mbedtls_ecp_restart_ctx *rs_ctx = NULL; |
#endif |
if( ctx->grp.pbits == 0 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( restart_enabled ) |
rs_ctx = &ctx->rs; |
#else |
(void) restart_enabled; |
#endif |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, |
f_rng, p_rng, rs_ctx ) ) != 0 ) |
return( ret ); |
#else |
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, |
f_rng, p_rng ) ) != 0 ) |
return( ret ); |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, |
blen ) ) != 0 ) |
return( ret ); |
buf += grp_len; |
blen -= grp_len; |
if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, |
&pt_len, buf, blen ) ) != 0 ) |
return( ret ); |
*olen = grp_len + pt_len; |
return( 0 ); |
} |
/* |
* Setup and write the ServerKeyExhange parameters (RFC 4492) |
* struct { |
* ECParameters curve_params; |
* ECPoint public; |
* } ServerECDHParams; |
*/ |
int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, |
unsigned char *buf, size_t blen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int restart_enabled = 0; |
ECDH_VALIDATE_RET( ctx != NULL ); |
ECDH_VALIDATE_RET( olen != NULL ); |
ECDH_VALIDATE_RET( buf != NULL ); |
ECDH_VALIDATE_RET( f_rng != NULL ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
restart_enabled = ctx->restart_enabled; |
#else |
(void) restart_enabled; |
#endif |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, |
f_rng, p_rng, restart_enabled ) ); |
#else |
switch( ctx->var ) |
{ |
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: |
return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, |
ctx->point_format, buf, blen, |
f_rng, p_rng, |
restart_enabled ) ); |
default: |
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
} |
#endif |
} |
static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, |
const unsigned char **buf, |
const unsigned char *end ) |
{ |
return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, |
end - *buf ) ); |
} |
/* |
* Read the ServerKeyExhange parameters (RFC 4492) |
* struct { |
* ECParameters curve_params; |
* ECPoint public; |
* } ServerECDHParams; |
*/ |
int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, |
const unsigned char **buf, |
const unsigned char *end ) |
{ |
int ret; |
mbedtls_ecp_group_id grp_id; |
ECDH_VALIDATE_RET( ctx != NULL ); |
ECDH_VALIDATE_RET( buf != NULL ); |
ECDH_VALIDATE_RET( *buf != NULL ); |
ECDH_VALIDATE_RET( end != NULL ); |
if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) |
!= 0 ) |
return( ret ); |
if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) |
return( ret ); |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ecdh_read_params_internal( ctx, buf, end ) ); |
#else |
switch( ctx->var ) |
{ |
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: |
return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, |
buf, end ) ); |
default: |
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
} |
#endif |
} |
static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, |
const mbedtls_ecp_keypair *key, |
mbedtls_ecdh_side side ) |
{ |
int ret; |
/* If it's not our key, just import the public part as Qp */ |
if( side == MBEDTLS_ECDH_THEIRS ) |
return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); |
/* Our key: import public (as Q) and private parts */ |
if( side != MBEDTLS_ECDH_OURS ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || |
( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
/* |
* Get parameters from a keypair |
*/ |
int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, |
const mbedtls_ecp_keypair *key, |
mbedtls_ecdh_side side ) |
{ |
int ret; |
ECDH_VALIDATE_RET( ctx != NULL ); |
ECDH_VALIDATE_RET( key != NULL ); |
ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || |
side == MBEDTLS_ECDH_THEIRS ); |
if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE ) |
{ |
/* This is the first call to get_params(). Set up the context |
* for use with the group. */ |
if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) |
return( ret ); |
} |
else |
{ |
/* This is not the first call to get_params(). Check that the |
* current key's group is the same as the context's, which was set |
* from the first key's group. */ |
if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ecdh_get_params_internal( ctx, key, side ) ); |
#else |
switch( ctx->var ) |
{ |
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: |
return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, |
key, side ) ); |
default: |
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
} |
#endif |
} |
static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, |
size_t *olen, int point_format, |
unsigned char *buf, size_t blen, |
int (*f_rng)(void *, |
unsigned char *, |
size_t), |
void *p_rng, |
int restart_enabled ) |
{ |
int ret; |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
mbedtls_ecp_restart_ctx *rs_ctx = NULL; |
#endif |
if( ctx->grp.pbits == 0 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( restart_enabled ) |
rs_ctx = &ctx->rs; |
#else |
(void) restart_enabled; |
#endif |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, |
f_rng, p_rng, rs_ctx ) ) != 0 ) |
return( ret ); |
#else |
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, |
f_rng, p_rng ) ) != 0 ) |
return( ret ); |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, |
buf, blen ); |
} |
/* |
* Setup and export the client public value |
*/ |
int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, |
unsigned char *buf, size_t blen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int restart_enabled = 0; |
ECDH_VALIDATE_RET( ctx != NULL ); |
ECDH_VALIDATE_RET( olen != NULL ); |
ECDH_VALIDATE_RET( buf != NULL ); |
ECDH_VALIDATE_RET( f_rng != NULL ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
restart_enabled = ctx->restart_enabled; |
#endif |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, |
f_rng, p_rng, restart_enabled ) ); |
#else |
switch( ctx->var ) |
{ |
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: |
return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, |
ctx->point_format, buf, blen, |
f_rng, p_rng, |
restart_enabled ) ); |
default: |
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
} |
#endif |
} |
static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, |
const unsigned char *buf, size_t blen ) |
{ |
int ret; |
const unsigned char *p = buf; |
if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, |
blen ) ) != 0 ) |
return( ret ); |
if( (size_t)( p - buf ) != blen ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
return( 0 ); |
} |
/* |
* Parse and import the client's public value |
*/ |
int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, |
const unsigned char *buf, size_t blen ) |
{ |
ECDH_VALIDATE_RET( ctx != NULL ); |
ECDH_VALIDATE_RET( buf != NULL ); |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ecdh_read_public_internal( ctx, buf, blen ) ); |
#else |
switch( ctx->var ) |
{ |
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: |
return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, |
buf, blen ) ); |
default: |
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
} |
#endif |
} |
static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, |
size_t *olen, unsigned char *buf, |
size_t blen, |
int (*f_rng)(void *, |
unsigned char *, |
size_t), |
void *p_rng, |
int restart_enabled ) |
{ |
int ret; |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
mbedtls_ecp_restart_ctx *rs_ctx = NULL; |
#endif |
if( ctx == NULL || ctx->grp.pbits == 0 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( restart_enabled ) |
rs_ctx = &ctx->rs; |
#else |
(void) restart_enabled; |
#endif |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, |
&ctx->d, f_rng, p_rng, |
rs_ctx ) ) != 0 ) |
{ |
return( ret ); |
} |
#else |
if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, |
&ctx->d, f_rng, p_rng ) ) != 0 ) |
{ |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
if( mbedtls_mpi_size( &ctx->z ) > blen ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
*olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); |
return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); |
} |
/* |
* Derive and export the shared secret |
*/ |
int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, |
unsigned char *buf, size_t blen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int restart_enabled = 0; |
ECDH_VALIDATE_RET( ctx != NULL ); |
ECDH_VALIDATE_RET( olen != NULL ); |
ECDH_VALIDATE_RET( buf != NULL ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
restart_enabled = ctx->restart_enabled; |
#endif |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, |
restart_enabled ) ); |
#else |
switch( ctx->var ) |
{ |
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: |
return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, |
blen, f_rng, p_rng, |
restart_enabled ) ); |
default: |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
#endif |
} |
#endif /* MBEDTLS_ECDH_C */ |
/programs/develop/libraries/kos_mbedtls/library/ecdsa.c |
---|
0,0 → 1,993 |
/* |
* Elliptic curve DSA |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* References: |
* |
* SEC1 http://www.secg.org/index.php?action=secg,docs_secg |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
#include "mbedtls/ecdsa.h" |
#include "mbedtls/asn1write.h" |
#include <string.h> |
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) |
#include "mbedtls/hmac_drbg.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/platform_util.h" |
/* Parameter validation macros based on platform_util.h */ |
#define ECDSA_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) |
#define ECDSA_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* Sub-context for ecdsa_verify() |
*/ |
struct mbedtls_ecdsa_restart_ver |
{ |
mbedtls_mpi u1, u2; /* intermediate values */ |
enum { /* what to do next? */ |
ecdsa_ver_init = 0, /* getting started */ |
ecdsa_ver_muladd, /* muladd step */ |
} state; |
}; |
/* |
* Init verify restart sub-context |
*/ |
static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) |
{ |
mbedtls_mpi_init( &ctx->u1 ); |
mbedtls_mpi_init( &ctx->u2 ); |
ctx->state = ecdsa_ver_init; |
} |
/* |
* Free the components of a verify restart sub-context |
*/ |
static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_mpi_free( &ctx->u1 ); |
mbedtls_mpi_free( &ctx->u2 ); |
ecdsa_restart_ver_init( ctx ); |
} |
/* |
* Sub-context for ecdsa_sign() |
*/ |
struct mbedtls_ecdsa_restart_sig |
{ |
int sign_tries; |
int key_tries; |
mbedtls_mpi k; /* per-signature random */ |
mbedtls_mpi r; /* r value */ |
enum { /* what to do next? */ |
ecdsa_sig_init = 0, /* getting started */ |
ecdsa_sig_mul, /* doing ecp_mul() */ |
ecdsa_sig_modn, /* mod N computations */ |
} state; |
}; |
/* |
* Init verify sign sub-context |
*/ |
static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) |
{ |
ctx->sign_tries = 0; |
ctx->key_tries = 0; |
mbedtls_mpi_init( &ctx->k ); |
mbedtls_mpi_init( &ctx->r ); |
ctx->state = ecdsa_sig_init; |
} |
/* |
* Free the components of a sign restart sub-context |
*/ |
static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_mpi_free( &ctx->k ); |
mbedtls_mpi_free( &ctx->r ); |
} |
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) |
/* |
* Sub-context for ecdsa_sign_det() |
*/ |
struct mbedtls_ecdsa_restart_det |
{ |
mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ |
enum { /* what to do next? */ |
ecdsa_det_init = 0, /* getting started */ |
ecdsa_det_sign, /* make signature */ |
} state; |
}; |
/* |
* Init verify sign_det sub-context |
*/ |
static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) |
{ |
mbedtls_hmac_drbg_init( &ctx->rng_ctx ); |
ctx->state = ecdsa_det_init; |
} |
/* |
* Free the components of a sign_det restart sub-context |
*/ |
static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_hmac_drbg_free( &ctx->rng_ctx ); |
ecdsa_restart_det_init( ctx ); |
} |
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ |
#define ECDSA_RS_ECP ( rs_ctx == NULL ? NULL : &rs_ctx->ecp ) |
/* Utility macro for checking and updating ops budget */ |
#define ECDSA_BUDGET( ops ) \ |
MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, ECDSA_RS_ECP, ops ) ); |
/* Call this when entering a function that needs its own sub-context */ |
#define ECDSA_RS_ENTER( SUB ) do { \ |
/* reset ops count for this call if top-level */ \ |
if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ |
rs_ctx->ecp.ops_done = 0; \ |
\ |
/* set up our own sub-context if needed */ \ |
if( mbedtls_ecp_restart_is_enabled() && \ |
rs_ctx != NULL && rs_ctx->SUB == NULL ) \ |
{ \ |
rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ |
if( rs_ctx->SUB == NULL ) \ |
return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ |
\ |
ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ |
} \ |
} while( 0 ) |
/* Call this when leaving a function that needs its own sub-context */ |
#define ECDSA_RS_LEAVE( SUB ) do { \ |
/* clear our sub-context when not in progress (done or error) */ \ |
if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ |
ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ |
{ \ |
ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ |
mbedtls_free( rs_ctx->SUB ); \ |
rs_ctx->SUB = NULL; \ |
} \ |
\ |
if( rs_ctx != NULL ) \ |
rs_ctx->ecp.depth--; \ |
} while( 0 ) |
#else /* MBEDTLS_ECP_RESTARTABLE */ |
#define ECDSA_RS_ECP NULL |
#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ |
#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx |
#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
/* |
* Derive a suitable integer for group grp from a buffer of length len |
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 |
*/ |
static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, |
const unsigned char *buf, size_t blen ) |
{ |
int ret; |
size_t n_size = ( grp->nbits + 7 ) / 8; |
size_t use_size = blen > n_size ? n_size : blen; |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); |
if( use_size * 8 > grp->nbits ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); |
/* While at it, reduce modulo N */ |
if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); |
cleanup: |
return( ret ); |
} |
#if !defined(MBEDTLS_ECDSA_SIGN_ALT) |
/* |
* Compute ECDSA signature of a hashed message (SEC1 4.1.3) |
* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) |
*/ |
static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, |
mbedtls_mpi *r, mbedtls_mpi *s, |
const mbedtls_mpi *d, const unsigned char *buf, size_t blen, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
int (*f_rng_blind)(void *, unsigned char *, size_t), |
void *p_rng_blind, |
mbedtls_ecdsa_restart_ctx *rs_ctx ) |
{ |
int ret, key_tries, sign_tries; |
int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; |
mbedtls_ecp_point R; |
mbedtls_mpi k, e, t; |
mbedtls_mpi *pk = &k, *pr = r; |
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ |
if( grp->N.p == NULL ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
/* Make sure d is in range 1..n-1 */ |
if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) |
return( MBEDTLS_ERR_ECP_INVALID_KEY ); |
mbedtls_ecp_point_init( &R ); |
mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); |
ECDSA_RS_ENTER( sig ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->sig != NULL ) |
{ |
/* redirect to our context */ |
p_sign_tries = &rs_ctx->sig->sign_tries; |
p_key_tries = &rs_ctx->sig->key_tries; |
pk = &rs_ctx->sig->k; |
pr = &rs_ctx->sig->r; |
/* jump to current step */ |
if( rs_ctx->sig->state == ecdsa_sig_mul ) |
goto mul; |
if( rs_ctx->sig->state == ecdsa_sig_modn ) |
goto modn; |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
*p_sign_tries = 0; |
do |
{ |
if( (*p_sign_tries)++ > 10 ) |
{ |
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; |
goto cleanup; |
} |
/* |
* Steps 1-3: generate a suitable ephemeral keypair |
* and set r = xR mod n |
*/ |
*p_key_tries = 0; |
do |
{ |
if( (*p_key_tries)++ > 10 ) |
{ |
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->sig != NULL ) |
rs_ctx->sig->state = ecdsa_sig_mul; |
mul: |
#endif |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, |
f_rng_blind, |
p_rng_blind, |
ECDSA_RS_ECP ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); |
} |
while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->sig != NULL ) |
rs_ctx->sig->state = ecdsa_sig_modn; |
modn: |
#endif |
/* |
* Accounting for everything up to the end of the loop |
* (step 6, but checking now avoids saving e and t) |
*/ |
ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); |
/* |
* Step 5: derive MPI from hashed message |
*/ |
MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); |
/* |
* Generate a random value to blind inv_mod in next step, |
* avoiding a potential timing leak. |
*/ |
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind, |
p_rng_blind ) ); |
/* |
* Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); |
} |
while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->sig != NULL ) |
mbedtls_mpi_copy( r, pr ); |
#endif |
cleanup: |
mbedtls_ecp_point_free( &R ); |
mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); |
ECDSA_RS_LEAVE( sig ); |
return( ret ); |
} |
/* |
* Compute ECDSA signature of a hashed message |
*/ |
int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, |
const mbedtls_mpi *d, const unsigned char *buf, size_t blen, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
ECDSA_VALIDATE_RET( grp != NULL ); |
ECDSA_VALIDATE_RET( r != NULL ); |
ECDSA_VALIDATE_RET( s != NULL ); |
ECDSA_VALIDATE_RET( d != NULL ); |
ECDSA_VALIDATE_RET( f_rng != NULL ); |
ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); |
/* Use the same RNG for both blinding and ephemeral key generation */ |
return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, |
f_rng, p_rng, f_rng, p_rng, NULL ) ); |
} |
#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ |
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) |
/* |
* Deterministic signature wrapper |
*/ |
static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, |
mbedtls_mpi *r, mbedtls_mpi *s, |
const mbedtls_mpi *d, const unsigned char *buf, size_t blen, |
mbedtls_md_type_t md_alg, |
int (*f_rng_blind)(void *, unsigned char *, size_t), |
void *p_rng_blind, |
mbedtls_ecdsa_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_hmac_drbg_context rng_ctx; |
mbedtls_hmac_drbg_context *p_rng = &rng_ctx; |
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; |
size_t grp_len = ( grp->nbits + 7 ) / 8; |
const mbedtls_md_info_t *md_info; |
mbedtls_mpi h; |
if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
mbedtls_mpi_init( &h ); |
mbedtls_hmac_drbg_init( &rng_ctx ); |
ECDSA_RS_ENTER( det ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->det != NULL ) |
{ |
/* redirect to our context */ |
p_rng = &rs_ctx->det->rng_ctx; |
/* jump to current step */ |
if( rs_ctx->det->state == ecdsa_det_sign ) |
goto sign; |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
/* Use private key and message hash (reduced) to initialize HMAC_DRBG */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); |
MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); |
mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->det != NULL ) |
rs_ctx->det->state = ecdsa_det_sign; |
sign: |
#endif |
#if defined(MBEDTLS_ECDSA_SIGN_ALT) |
ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, |
mbedtls_hmac_drbg_random, p_rng ); |
#else |
if( f_rng_blind != NULL ) |
ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, |
mbedtls_hmac_drbg_random, p_rng, |
f_rng_blind, p_rng_blind, rs_ctx ); |
else |
{ |
mbedtls_hmac_drbg_context *p_rng_blind_det; |
#if !defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* To avoid reusing rng_ctx and risking incorrect behavior we seed a |
* second HMAC-DRBG with the same seed. We also apply a label to avoid |
* reusing the bits of the ephemeral key for blinding and eliminate the |
* risk that they leak this way. |
*/ |
const char* blind_label = "BLINDING CONTEXT"; |
mbedtls_hmac_drbg_context rng_ctx_blind; |
mbedtls_hmac_drbg_init( &rng_ctx_blind ); |
p_rng_blind_det = &rng_ctx_blind; |
mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info, |
data, 2 * grp_len ); |
ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det, |
(const unsigned char*) blind_label, |
strlen( blind_label ) ); |
if( ret != 0 ) |
{ |
mbedtls_hmac_drbg_free( &rng_ctx_blind ); |
goto cleanup; |
} |
#else |
/* |
* In the case of restartable computations we would either need to store |
* the second RNG in the restart context too or set it up at every |
* restart. The first option would penalize the correct application of |
* the function and the second would defeat the purpose of the |
* restartable feature. |
* |
* Therefore in this case we reuse the original RNG. This comes with the |
* price that the resulting signature might not be a valid deterministic |
* ECDSA signature with a very low probability (same magnitude as |
* successfully guessing the private key). However even then it is still |
* a valid ECDSA signature. |
*/ |
p_rng_blind_det = p_rng; |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
/* |
* Since the output of the RNGs is always the same for the same key and |
* message, this limits the efficiency of blinding and leaks information |
* through side channels. After mbedtls_ecdsa_sign_det() is removed NULL |
* won't be a valid value for f_rng_blind anymore. Therefore it should |
* be checked by the caller and this branch and check can be removed. |
*/ |
ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, |
mbedtls_hmac_drbg_random, p_rng, |
mbedtls_hmac_drbg_random, p_rng_blind_det, |
rs_ctx ); |
#if !defined(MBEDTLS_ECP_RESTARTABLE) |
mbedtls_hmac_drbg_free( &rng_ctx_blind ); |
#endif |
} |
#endif /* MBEDTLS_ECDSA_SIGN_ALT */ |
cleanup: |
mbedtls_hmac_drbg_free( &rng_ctx ); |
mbedtls_mpi_free( &h ); |
ECDSA_RS_LEAVE( det ); |
return( ret ); |
} |
/* |
* Deterministic signature wrappers |
*/ |
int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, |
mbedtls_mpi *s, const mbedtls_mpi *d, |
const unsigned char *buf, size_t blen, |
mbedtls_md_type_t md_alg ) |
{ |
ECDSA_VALIDATE_RET( grp != NULL ); |
ECDSA_VALIDATE_RET( r != NULL ); |
ECDSA_VALIDATE_RET( s != NULL ); |
ECDSA_VALIDATE_RET( d != NULL ); |
ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); |
return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, |
NULL, NULL, NULL ) ); |
} |
int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, |
mbedtls_mpi *s, const mbedtls_mpi *d, |
const unsigned char *buf, size_t blen, |
mbedtls_md_type_t md_alg, |
int (*f_rng_blind)(void *, unsigned char *, |
size_t), |
void *p_rng_blind ) |
{ |
ECDSA_VALIDATE_RET( grp != NULL ); |
ECDSA_VALIDATE_RET( r != NULL ); |
ECDSA_VALIDATE_RET( s != NULL ); |
ECDSA_VALIDATE_RET( d != NULL ); |
ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); |
ECDSA_VALIDATE_RET( f_rng_blind != NULL ); |
return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, |
f_rng_blind, p_rng_blind, NULL ) ); |
} |
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ |
#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) |
/* |
* Verify ECDSA signature of hashed message (SEC1 4.1.4) |
* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) |
*/ |
static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, |
const unsigned char *buf, size_t blen, |
const mbedtls_ecp_point *Q, |
const mbedtls_mpi *r, const mbedtls_mpi *s, |
mbedtls_ecdsa_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_mpi e, s_inv, u1, u2; |
mbedtls_ecp_point R; |
mbedtls_mpi *pu1 = &u1, *pu2 = &u2; |
mbedtls_ecp_point_init( &R ); |
mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); |
mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); |
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ |
if( grp->N.p == NULL ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
ECDSA_RS_ENTER( ver ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->ver != NULL ) |
{ |
/* redirect to our context */ |
pu1 = &rs_ctx->ver->u1; |
pu2 = &rs_ctx->ver->u2; |
/* jump to current step */ |
if( rs_ctx->ver->state == ecdsa_ver_muladd ) |
goto muladd; |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
/* |
* Step 1: make sure r and s are in range 1..n-1 |
*/ |
if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || |
mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) |
{ |
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; |
goto cleanup; |
} |
/* |
* Step 3: derive MPI from hashed message |
*/ |
MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); |
/* |
* Step 4: u1 = e / s mod n, u2 = r / s mod n |
*/ |
ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->ver != NULL ) |
rs_ctx->ver->state = ecdsa_ver_muladd; |
muladd: |
#endif |
/* |
* Step 5: R = u1 G + u2 Q |
*/ |
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, |
&R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); |
if( mbedtls_ecp_is_zero( &R ) ) |
{ |
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; |
goto cleanup; |
} |
/* |
* Step 6: convert xR to an integer (no-op) |
* Step 7: reduce xR mod n (gives v) |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); |
/* |
* Step 8: check if v (that is, R.X) is equal to r |
*/ |
if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) |
{ |
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; |
goto cleanup; |
} |
cleanup: |
mbedtls_ecp_point_free( &R ); |
mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); |
mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); |
ECDSA_RS_LEAVE( ver ); |
return( ret ); |
} |
/* |
* Verify ECDSA signature of hashed message |
*/ |
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, |
const unsigned char *buf, size_t blen, |
const mbedtls_ecp_point *Q, |
const mbedtls_mpi *r, |
const mbedtls_mpi *s) |
{ |
ECDSA_VALIDATE_RET( grp != NULL ); |
ECDSA_VALIDATE_RET( Q != NULL ); |
ECDSA_VALIDATE_RET( r != NULL ); |
ECDSA_VALIDATE_RET( s != NULL ); |
ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); |
return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); |
} |
#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ |
/* |
* Convert a signature (given by context) to ASN.1 |
*/ |
static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, |
unsigned char *sig, size_t *slen ) |
{ |
int ret; |
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; |
unsigned char *p = buf + sizeof( buf ); |
size_t len = 0; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); |
memcpy( sig, p, len ); |
*slen = len; |
return( 0 ); |
} |
/* |
* Compute and write signature |
*/ |
int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, |
mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hlen, |
unsigned char *sig, size_t *slen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
mbedtls_ecdsa_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_mpi r, s; |
ECDSA_VALIDATE_RET( ctx != NULL ); |
ECDSA_VALIDATE_RET( hash != NULL ); |
ECDSA_VALIDATE_RET( sig != NULL ); |
ECDSA_VALIDATE_RET( slen != NULL ); |
mbedtls_mpi_init( &r ); |
mbedtls_mpi_init( &s ); |
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) |
MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, |
hash, hlen, md_alg, f_rng, |
p_rng, rs_ctx ) ); |
#else |
(void) md_alg; |
#if defined(MBEDTLS_ECDSA_SIGN_ALT) |
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, |
hash, hlen, f_rng, p_rng ) ); |
#else |
/* Use the same RNG for both blinding and ephemeral key generation */ |
MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, |
hash, hlen, f_rng, p_rng, f_rng, |
p_rng, rs_ctx ) ); |
#endif /* MBEDTLS_ECDSA_SIGN_ALT */ |
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ |
MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); |
cleanup: |
mbedtls_mpi_free( &r ); |
mbedtls_mpi_free( &s ); |
return( ret ); |
} |
/* |
* Compute and write signature |
*/ |
int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, |
mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hlen, |
unsigned char *sig, size_t *slen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
ECDSA_VALIDATE_RET( ctx != NULL ); |
ECDSA_VALIDATE_RET( hash != NULL ); |
ECDSA_VALIDATE_RET( sig != NULL ); |
ECDSA_VALIDATE_RET( slen != NULL ); |
return( mbedtls_ecdsa_write_signature_restartable( |
ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \ |
defined(MBEDTLS_ECDSA_DETERMINISTIC) |
int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, |
const unsigned char *hash, size_t hlen, |
unsigned char *sig, size_t *slen, |
mbedtls_md_type_t md_alg ) |
{ |
ECDSA_VALIDATE_RET( ctx != NULL ); |
ECDSA_VALIDATE_RET( hash != NULL ); |
ECDSA_VALIDATE_RET( sig != NULL ); |
ECDSA_VALIDATE_RET( slen != NULL ); |
return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, |
NULL, NULL ) ); |
} |
#endif |
/* |
* Read and check signature |
*/ |
int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, |
const unsigned char *hash, size_t hlen, |
const unsigned char *sig, size_t slen ) |
{ |
ECDSA_VALIDATE_RET( ctx != NULL ); |
ECDSA_VALIDATE_RET( hash != NULL ); |
ECDSA_VALIDATE_RET( sig != NULL ); |
return( mbedtls_ecdsa_read_signature_restartable( |
ctx, hash, hlen, sig, slen, NULL ) ); |
} |
/* |
* Restartable read and check signature |
*/ |
int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, |
const unsigned char *hash, size_t hlen, |
const unsigned char *sig, size_t slen, |
mbedtls_ecdsa_restart_ctx *rs_ctx ) |
{ |
int ret; |
unsigned char *p = (unsigned char *) sig; |
const unsigned char *end = sig + slen; |
size_t len; |
mbedtls_mpi r, s; |
ECDSA_VALIDATE_RET( ctx != NULL ); |
ECDSA_VALIDATE_RET( hash != NULL ); |
ECDSA_VALIDATE_RET( sig != NULL ); |
mbedtls_mpi_init( &r ); |
mbedtls_mpi_init( &s ); |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
goto cleanup; |
} |
if( p + len != end ) |
{ |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; |
goto cleanup; |
} |
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || |
( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) |
{ |
ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
goto cleanup; |
} |
#if defined(MBEDTLS_ECDSA_VERIFY_ALT) |
if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, |
&ctx->Q, &r, &s ) ) != 0 ) |
goto cleanup; |
#else |
if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, |
&ctx->Q, &r, &s, rs_ctx ) ) != 0 ) |
goto cleanup; |
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ |
/* At this point we know that the buffer starts with a valid signature. |
* Return 0 if the buffer just contains the signature, and a specific |
* error code if the valid signature is followed by more data. */ |
if( p != end ) |
ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; |
cleanup: |
mbedtls_mpi_free( &r ); |
mbedtls_mpi_free( &s ); |
return( ret ); |
} |
#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) |
/* |
* Generate key pair |
*/ |
int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
int ret = 0; |
ECDSA_VALIDATE_RET( ctx != NULL ); |
ECDSA_VALIDATE_RET( f_rng != NULL ); |
ret = mbedtls_ecp_group_load( &ctx->grp, gid ); |
if( ret != 0 ) |
return( ret ); |
return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, |
&ctx->Q, f_rng, p_rng ) ); |
} |
#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ |
/* |
* Set context from an mbedtls_ecp_keypair |
*/ |
int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) |
{ |
int ret; |
ECDSA_VALIDATE_RET( ctx != NULL ); |
ECDSA_VALIDATE_RET( key != NULL ); |
if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || |
( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || |
( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) |
{ |
mbedtls_ecdsa_free( ctx ); |
} |
return( ret ); |
} |
/* |
* Initialize context |
*/ |
void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) |
{ |
ECDSA_VALIDATE( ctx != NULL ); |
mbedtls_ecp_keypair_init( ctx ); |
} |
/* |
* Free context |
*/ |
void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_ecp_keypair_free( ctx ); |
} |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* Initialize a restart context |
*/ |
void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) |
{ |
ECDSA_VALIDATE( ctx != NULL ); |
mbedtls_ecp_restart_init( &ctx->ecp ); |
ctx->ver = NULL; |
ctx->sig = NULL; |
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) |
ctx->det = NULL; |
#endif |
} |
/* |
* Free the components of a restart context |
*/ |
void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_ecp_restart_free( &ctx->ecp ); |
ecdsa_restart_ver_free( ctx->ver ); |
mbedtls_free( ctx->ver ); |
ctx->ver = NULL; |
ecdsa_restart_sig_free( ctx->sig ); |
mbedtls_free( ctx->sig ); |
ctx->sig = NULL; |
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) |
ecdsa_restart_det_free( ctx->det ); |
mbedtls_free( ctx->det ); |
ctx->det = NULL; |
#endif |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
#endif /* MBEDTLS_ECDSA_C */ |
/programs/develop/libraries/kos_mbedtls/library/ecjpake.c |
---|
0,0 → 1,1142 |
/* |
* Elliptic curve J-PAKE |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* References in the code are to the Thread v1.0 Specification, |
* available to members of the Thread Group http://threadgroup.org/ |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ECJPAKE_C) |
#include "mbedtls/ecjpake.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if !defined(MBEDTLS_ECJPAKE_ALT) |
/* Parameter validation macros based on platform_util.h */ |
#define ECJPAKE_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) |
#define ECJPAKE_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* Convert a mbedtls_ecjpake_role to identifier string |
*/ |
static const char * const ecjpake_id[] = { |
"client", |
"server" |
}; |
#define ID_MINE ( ecjpake_id[ ctx->role ] ) |
#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) |
/* |
* Initialize context |
*/ |
void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) |
{ |
ECJPAKE_VALIDATE( ctx != NULL ); |
ctx->md_info = NULL; |
mbedtls_ecp_group_init( &ctx->grp ); |
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; |
mbedtls_ecp_point_init( &ctx->Xm1 ); |
mbedtls_ecp_point_init( &ctx->Xm2 ); |
mbedtls_ecp_point_init( &ctx->Xp1 ); |
mbedtls_ecp_point_init( &ctx->Xp2 ); |
mbedtls_ecp_point_init( &ctx->Xp ); |
mbedtls_mpi_init( &ctx->xm1 ); |
mbedtls_mpi_init( &ctx->xm2 ); |
mbedtls_mpi_init( &ctx->s ); |
} |
/* |
* Free context |
*/ |
void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
ctx->md_info = NULL; |
mbedtls_ecp_group_free( &ctx->grp ); |
mbedtls_ecp_point_free( &ctx->Xm1 ); |
mbedtls_ecp_point_free( &ctx->Xm2 ); |
mbedtls_ecp_point_free( &ctx->Xp1 ); |
mbedtls_ecp_point_free( &ctx->Xp2 ); |
mbedtls_ecp_point_free( &ctx->Xp ); |
mbedtls_mpi_free( &ctx->xm1 ); |
mbedtls_mpi_free( &ctx->xm2 ); |
mbedtls_mpi_free( &ctx->s ); |
} |
/* |
* Setup context |
*/ |
int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, |
mbedtls_ecjpake_role role, |
mbedtls_md_type_t hash, |
mbedtls_ecp_group_id curve, |
const unsigned char *secret, |
size_t len ) |
{ |
int ret; |
ECJPAKE_VALIDATE_RET( ctx != NULL ); |
ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT || |
role == MBEDTLS_ECJPAKE_SERVER ); |
ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 ); |
ctx->role = role; |
if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) |
return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); |
cleanup: |
if( ret != 0 ) |
mbedtls_ecjpake_free( ctx ); |
return( ret ); |
} |
/* |
* Check if context is ready for use |
*/ |
int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) |
{ |
ECJPAKE_VALIDATE_RET( ctx != NULL ); |
if( ctx->md_info == NULL || |
ctx->grp.id == MBEDTLS_ECP_DP_NONE || |
ctx->s.p == NULL ) |
{ |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
return( 0 ); |
} |
/* |
* Write a point plus its length to a buffer |
*/ |
static int ecjpake_write_len_point( unsigned char **p, |
const unsigned char *end, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *P ) |
{ |
int ret; |
size_t len; |
/* Need at least 4 for length plus 1 for point */ |
if( end < *p || end - *p < 5 ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
ret = mbedtls_ecp_point_write_binary( grp, P, pf, |
&len, *p + 4, end - ( *p + 4 ) ); |
if( ret != 0 ) |
return( ret ); |
(*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF ); |
(*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF ); |
(*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF ); |
(*p)[3] = (unsigned char)( ( len ) & 0xFF ); |
*p += 4 + len; |
return( 0 ); |
} |
/* |
* Size of the temporary buffer for ecjpake_hash: |
* 3 EC points plus their length, plus ID and its length (4 + 6 bytes) |
*/ |
#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) |
/* |
* Compute hash for ZKP (7.4.2.2.2.1) |
*/ |
static int ecjpake_hash( const mbedtls_md_info_t *md_info, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *G, |
const mbedtls_ecp_point *V, |
const mbedtls_ecp_point *X, |
const char *id, |
mbedtls_mpi *h ) |
{ |
int ret; |
unsigned char buf[ECJPAKE_HASH_BUF_LEN]; |
unsigned char *p = buf; |
const unsigned char *end = buf + sizeof( buf ); |
const size_t id_len = strlen( id ); |
unsigned char hash[MBEDTLS_MD_MAX_SIZE]; |
/* Write things to temporary buffer */ |
MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); |
MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); |
MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); |
if( end - p < 4 ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
*p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF ); |
*p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF ); |
*p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( id_len ) & 0xFF ); |
if( end < p || (size_t)( end - p ) < id_len ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
memcpy( p, id, id_len ); |
p += id_len; |
/* Compute hash */ |
MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) ); |
/* Turn it into an integer mod n */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, |
mbedtls_md_get_size( md_info ) ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) |
*/ |
static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *G, |
const mbedtls_ecp_point *X, |
const char *id, |
const unsigned char **p, |
const unsigned char *end ) |
{ |
int ret; |
mbedtls_ecp_point V, VV; |
mbedtls_mpi r, h; |
size_t r_len; |
mbedtls_ecp_point_init( &V ); |
mbedtls_ecp_point_init( &VV ); |
mbedtls_mpi_init( &r ); |
mbedtls_mpi_init( &h ); |
/* |
* struct { |
* ECPoint V; |
* opaque r<1..2^8-1>; |
* } ECSchnorrZKP; |
*/ |
if( end < *p ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); |
if( end < *p || (size_t)( end - *p ) < 1 ) |
{ |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
goto cleanup; |
} |
r_len = *(*p)++; |
if( end < *p || (size_t)( end - *p ) < r_len ) |
{ |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); |
*p += r_len; |
/* |
* Verification |
*/ |
MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, |
&VV, &h, X, &r, G ) ); |
if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) |
{ |
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; |
goto cleanup; |
} |
cleanup: |
mbedtls_ecp_point_free( &V ); |
mbedtls_ecp_point_free( &VV ); |
mbedtls_mpi_free( &r ); |
mbedtls_mpi_free( &h ); |
return( ret ); |
} |
/* |
* Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) |
*/ |
static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *G, |
const mbedtls_mpi *x, |
const mbedtls_ecp_point *X, |
const char *id, |
unsigned char **p, |
const unsigned char *end, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
mbedtls_ecp_point V; |
mbedtls_mpi v; |
mbedtls_mpi h; /* later recycled to hold r */ |
size_t len; |
if( end < *p ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
mbedtls_ecp_point_init( &V ); |
mbedtls_mpi_init( &v ); |
mbedtls_mpi_init( &h ); |
/* Compute signature */ |
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, |
G, &v, &V, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ |
/* Write it out */ |
MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, |
pf, &len, *p, end - *p ) ); |
*p += len; |
len = mbedtls_mpi_size( &h ); /* actually r */ |
if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) |
{ |
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; |
goto cleanup; |
} |
*(*p)++ = (unsigned char)( len & 0xFF ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ |
*p += len; |
cleanup: |
mbedtls_ecp_point_free( &V ); |
mbedtls_mpi_free( &v ); |
mbedtls_mpi_free( &h ); |
return( ret ); |
} |
/* |
* Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof |
* Output: verified public key X |
*/ |
static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *G, |
mbedtls_ecp_point *X, |
const char *id, |
const unsigned char **p, |
const unsigned char *end ) |
{ |
int ret; |
if( end < *p ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
/* |
* struct { |
* ECPoint X; |
* ECSchnorrZKP zkp; |
* } ECJPAKEKeyKP; |
*/ |
MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); |
if( mbedtls_ecp_is_zero( X ) ) |
{ |
ret = MBEDTLS_ERR_ECP_INVALID_KEY; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Generate an ECJPAKEKeyKP |
* Output: the serialized structure, plus private/public key pair |
*/ |
static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *G, |
mbedtls_mpi *x, |
mbedtls_ecp_point *X, |
const char *id, |
unsigned char **p, |
const unsigned char *end, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
size_t len; |
if( end < *p ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
/* Generate key (7.4.2.3.1) and write it out */ |
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, |
f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, |
pf, &len, *p, end - *p ) ); |
*p += len; |
/* Generate and write proof */ |
MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, |
p, end, f_rng, p_rng ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs |
* Ouputs: verified peer public keys Xa, Xb |
*/ |
static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *G, |
mbedtls_ecp_point *Xa, |
mbedtls_ecp_point *Xb, |
const char *id, |
const unsigned char *buf, |
size_t len ) |
{ |
int ret; |
const unsigned char *p = buf; |
const unsigned char *end = buf + len; |
/* |
* struct { |
* ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; |
* } ECJPAKEKeyKPPairList; |
*/ |
MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); |
MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); |
if( p != end ) |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
cleanup: |
return( ret ); |
} |
/* |
* Generate a ECJPAKEKeyKPPairList |
* Outputs: the serialized structure, plus two private/public key pairs |
*/ |
static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, |
const mbedtls_ecp_group *grp, |
const int pf, |
const mbedtls_ecp_point *G, |
mbedtls_mpi *xm1, |
mbedtls_ecp_point *Xa, |
mbedtls_mpi *xm2, |
mbedtls_ecp_point *Xb, |
const char *id, |
unsigned char *buf, |
size_t len, |
size_t *olen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
unsigned char *p = buf; |
const unsigned char *end = buf + len; |
MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, |
&p, end, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, |
&p, end, f_rng, p_rng ) ); |
*olen = p - buf; |
cleanup: |
return( ret ); |
} |
/* |
* Read and process the first round message |
*/ |
int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, |
const unsigned char *buf, |
size_t len ) |
{ |
ECJPAKE_VALIDATE_RET( ctx != NULL ); |
ECJPAKE_VALIDATE_RET( buf != NULL ); |
return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, |
&ctx->grp.G, |
&ctx->Xp1, &ctx->Xp2, ID_PEER, |
buf, len ) ); |
} |
/* |
* Generate and write the first round message |
*/ |
int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, |
unsigned char *buf, size_t len, size_t *olen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
ECJPAKE_VALIDATE_RET( ctx != NULL ); |
ECJPAKE_VALIDATE_RET( buf != NULL ); |
ECJPAKE_VALIDATE_RET( olen != NULL ); |
ECJPAKE_VALIDATE_RET( f_rng != NULL ); |
return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, |
&ctx->grp.G, |
&ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, |
ID_MINE, buf, len, olen, f_rng, p_rng ) ); |
} |
/* |
* Compute the sum of three points R = A + B + C |
*/ |
static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_ecp_point *A, |
const mbedtls_ecp_point *B, |
const mbedtls_ecp_point *C ) |
{ |
int ret; |
mbedtls_mpi one; |
mbedtls_mpi_init( &one ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); |
cleanup: |
mbedtls_mpi_free( &one ); |
return( ret ); |
} |
/* |
* Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) |
*/ |
int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, |
const unsigned char *buf, |
size_t len ) |
{ |
int ret; |
const unsigned char *p = buf; |
const unsigned char *end = buf + len; |
mbedtls_ecp_group grp; |
mbedtls_ecp_point G; /* C: GB, S: GA */ |
ECJPAKE_VALIDATE_RET( ctx != NULL ); |
ECJPAKE_VALIDATE_RET( buf != NULL ); |
mbedtls_ecp_group_init( &grp ); |
mbedtls_ecp_point_init( &G ); |
/* |
* Server: GA = X3 + X4 + X1 (7.4.2.6.1) |
* Client: GB = X1 + X2 + X3 (7.4.2.5.1) |
* Unified: G = Xm1 + Xm2 + Xp1 |
* We need that before parsing in order to check Xp as we read it |
*/ |
MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, |
&ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); |
/* |
* struct { |
* ECParameters curve_params; // only client reading server msg |
* ECJPAKEKeyKP ecjpake_key_kp; |
* } Client/ServerECJPAKEParams; |
*/ |
if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); |
if( grp.id != ctx->grp.id ) |
{ |
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; |
goto cleanup; |
} |
} |
MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, |
ctx->point_format, |
&G, &ctx->Xp, ID_PEER, &p, end ) ); |
if( p != end ) |
{ |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
goto cleanup; |
} |
cleanup: |
mbedtls_ecp_group_free( &grp ); |
mbedtls_ecp_point_free( &G ); |
return( ret ); |
} |
/* |
* Compute R = +/- X * S mod N, taking care not to leak S |
*/ |
static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, |
const mbedtls_mpi *X, |
const mbedtls_mpi *S, |
const mbedtls_mpi *N, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
mbedtls_mpi b; /* Blinding value, then s + N * blinding */ |
mbedtls_mpi_init( &b ); |
/* b = s + rnd-128-bit * N */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); |
/* R = sign * X * b mod N */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); |
R->s *= sign; |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); |
cleanup: |
mbedtls_mpi_free( &b ); |
return( ret ); |
} |
/* |
* Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) |
*/ |
int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, |
unsigned char *buf, size_t len, size_t *olen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
mbedtls_ecp_point G; /* C: GA, S: GB */ |
mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ |
mbedtls_mpi xm; /* C: xc, S: xs */ |
unsigned char *p = buf; |
const unsigned char *end = buf + len; |
size_t ec_len; |
ECJPAKE_VALIDATE_RET( ctx != NULL ); |
ECJPAKE_VALIDATE_RET( buf != NULL ); |
ECJPAKE_VALIDATE_RET( olen != NULL ); |
ECJPAKE_VALIDATE_RET( f_rng != NULL ); |
mbedtls_ecp_point_init( &G ); |
mbedtls_ecp_point_init( &Xm ); |
mbedtls_mpi_init( &xm ); |
/* |
* First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) |
* |
* Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA |
* Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB |
* Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G |
*/ |
MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, |
&ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); |
MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, |
&ctx->grp.N, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); |
/* |
* Now write things out |
* |
* struct { |
* ECParameters curve_params; // only server writing its message |
* ECJPAKEKeyKP ecjpake_key_kp; |
* } Client/ServerECJPAKEParams; |
*/ |
if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) |
{ |
if( end < p ) |
{ |
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, |
p, end - p ) ); |
p += ec_len; |
} |
if( end < p ) |
{ |
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, |
ctx->point_format, &ec_len, p, end - p ) ); |
p += ec_len; |
MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, |
ctx->point_format, |
&G, &xm, &Xm, ID_MINE, |
&p, end, f_rng, p_rng ) ); |
*olen = p - buf; |
cleanup: |
mbedtls_ecp_point_free( &G ); |
mbedtls_ecp_point_free( &Xm ); |
mbedtls_mpi_free( &xm ); |
return( ret ); |
} |
/* |
* Derive PMS (7.4.2.7 / 7.4.2.8) |
*/ |
int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, |
unsigned char *buf, size_t len, size_t *olen, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
mbedtls_ecp_point K; |
mbedtls_mpi m_xm2_s, one; |
unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; |
size_t x_bytes; |
ECJPAKE_VALIDATE_RET( ctx != NULL ); |
ECJPAKE_VALIDATE_RET( buf != NULL ); |
ECJPAKE_VALIDATE_RET( olen != NULL ); |
ECJPAKE_VALIDATE_RET( f_rng != NULL ); |
*olen = mbedtls_md_get_size( ctx->md_info ); |
if( len < *olen ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
mbedtls_ecp_point_init( &K ); |
mbedtls_mpi_init( &m_xm2_s ); |
mbedtls_mpi_init( &one ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); |
/* |
* Client: K = ( Xs - X4 * x2 * s ) * x2 |
* Server: K = ( Xc - X2 * x4 * s ) * x4 |
* Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 |
*/ |
MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, |
&ctx->grp.N, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, |
&one, &ctx->Xp, |
&m_xm2_s, &ctx->Xp2 ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, |
f_rng, p_rng ) ); |
/* PMS = SHA-256( K.X ) */ |
x_bytes = ( ctx->grp.pbits + 7 ) / 8; |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); |
MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); |
cleanup: |
mbedtls_ecp_point_free( &K ); |
mbedtls_mpi_free( &m_xm2_s ); |
mbedtls_mpi_free( &one ); |
return( ret ); |
} |
#undef ID_MINE |
#undef ID_PEER |
#endif /* ! MBEDTLS_ECJPAKE_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif |
#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ |
!defined(MBEDTLS_SHA256_C) |
int mbedtls_ecjpake_self_test( int verbose ) |
{ |
(void) verbose; |
return( 0 ); |
} |
#else |
static const unsigned char ecjpake_test_password[] = { |
0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, |
0x65, 0x73, 0x74 |
}; |
static const unsigned char ecjpake_test_x1[] = { |
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, |
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 |
}; |
static const unsigned char ecjpake_test_x2[] = { |
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, |
0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 |
}; |
static const unsigned char ecjpake_test_x3[] = { |
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, |
0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 |
}; |
static const unsigned char ecjpake_test_x4[] = { |
0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, |
0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, |
0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 |
}; |
static const unsigned char ecjpake_test_cli_one[] = { |
0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, |
0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, |
0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, |
0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, |
0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, |
0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, |
0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, |
0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, |
0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, |
0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, |
0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, |
0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, |
0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, |
0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, |
0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, |
0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, |
0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, |
0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, |
0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, |
0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, |
0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, |
0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, |
0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, |
0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, |
0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, |
0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, |
0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, |
0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 |
}; |
static const unsigned char ecjpake_test_srv_one[] = { |
0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, |
0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, |
0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, |
0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, |
0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, |
0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, |
0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, |
0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, |
0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, |
0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, |
0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, |
0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, |
0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, |
0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, |
0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, |
0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, |
0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, |
0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, |
0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, |
0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, |
0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, |
0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, |
0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, |
0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, |
0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, |
0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, |
0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, |
0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 |
}; |
static const unsigned char ecjpake_test_srv_two[] = { |
0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, |
0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, |
0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, |
0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, |
0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, |
0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, |
0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, |
0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, |
0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, |
0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, |
0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, |
0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, |
0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, |
0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c |
}; |
static const unsigned char ecjpake_test_cli_two[] = { |
0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, |
0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, |
0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, |
0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, |
0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, |
0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, |
0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, |
0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, |
0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, |
0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, |
0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, |
0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, |
0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, |
0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c |
}; |
static const unsigned char ecjpake_test_pms[] = { |
0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, |
0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, |
0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 |
}; |
/* Load my private keys and generate the corresponding public keys */ |
static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, |
const unsigned char *xm1, size_t len1, |
const unsigned char *xm2, size_t len2 ) |
{ |
int ret; |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, |
&ctx->grp.G, NULL, NULL ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, |
&ctx->grp.G, NULL, NULL ) ); |
cleanup: |
return( ret ); |
} |
/* For tests we don't need a secure RNG; |
* use the LGC from Numerical Recipes for simplicity */ |
static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) |
{ |
static uint32_t x = 42; |
(void) p; |
while( len > 0 ) |
{ |
size_t use_len = len > 4 ? 4 : len; |
x = 1664525 * x + 1013904223; |
memcpy( out, &x, use_len ); |
out += use_len; |
len -= use_len; |
} |
return( 0 ); |
} |
#define TEST_ASSERT( x ) \ |
do { \ |
if( x ) \ |
ret = 0; \ |
else \ |
{ \ |
ret = 1; \ |
goto cleanup; \ |
} \ |
} while( 0 ) |
/* |
* Checkup routine |
*/ |
int mbedtls_ecjpake_self_test( int verbose ) |
{ |
int ret; |
mbedtls_ecjpake_context cli; |
mbedtls_ecjpake_context srv; |
unsigned char buf[512], pms[32]; |
size_t len, pmslen; |
mbedtls_ecjpake_init( &cli ); |
mbedtls_ecjpake_init( &srv ); |
if( verbose != 0 ) |
mbedtls_printf( " ECJPAKE test #0 (setup): " ); |
TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, |
MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, |
ecjpake_test_password, |
sizeof( ecjpake_test_password ) ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, |
MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, |
ecjpake_test_password, |
sizeof( ecjpake_test_password ) ) == 0 ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); |
TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, |
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, |
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, |
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, |
pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, |
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, |
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( len == pmslen ); |
TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); |
/* Simulate generation of round one */ |
MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, |
ecjpake_test_x1, sizeof( ecjpake_test_x1 ), |
ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); |
MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, |
ecjpake_test_x3, sizeof( ecjpake_test_x3 ), |
ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); |
/* Read round one */ |
TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, |
ecjpake_test_cli_one, |
sizeof( ecjpake_test_cli_one ) ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, |
ecjpake_test_srv_one, |
sizeof( ecjpake_test_srv_one ) ) == 0 ); |
/* Skip generation of round two, read round two */ |
TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, |
ecjpake_test_srv_two, |
sizeof( ecjpake_test_srv_two ) ) == 0 ); |
TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, |
ecjpake_test_cli_two, |
sizeof( ecjpake_test_cli_two ) ) == 0 ); |
/* Server derives PMS */ |
TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, |
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); |
TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); |
memset( buf, 0, len ); /* Avoid interferences with next step */ |
/* Client derives PMS */ |
TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, |
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); |
TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); |
TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
cleanup: |
mbedtls_ecjpake_free( &cli ); |
mbedtls_ecjpake_free( &srv ); |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( ret ); |
} |
#undef TEST_ASSERT |
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_ECJPAKE_C */ |
/programs/develop/libraries/kos_mbedtls/library/ecp.c |
---|
0,0 → 1,3029 |
/* |
* Elliptic curves over GF(p): generic functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* References: |
* |
* SEC1 http://www.secg.org/index.php?action=secg,docs_secg |
* GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone |
* FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf |
* RFC 4492 for the related TLS structures and constants |
* RFC 7748 for the Curve448 and Curve25519 curve definitions |
* |
* [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf |
* |
* [2] CORON, Jean-S'ebastien. Resistance against differential power analysis |
* for elliptic curve cryptosystems. In : Cryptographic Hardware and |
* Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. |
* <http://link.springer.com/chapter/10.1007/3-540-48059-5_25> |
* |
* [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to |
* render ECC resistant against Side Channel Attacks. IACR Cryptology |
* ePrint Archive, 2004, vol. 2004, p. 342. |
* <http://eprint.iacr.org/2004/342.pdf> |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
/** |
* \brief Function level alternative implementation. |
* |
* The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to |
* replace certain functions in this module. The alternative implementations are |
* typically hardware accelerators and need to activate the hardware before the |
* computation starts and deactivate it after it finishes. The |
* mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve |
* this purpose. |
* |
* To preserve the correct functionality the following conditions must hold: |
* |
* - The alternative implementation must be activated by |
* mbedtls_internal_ecp_init() before any of the replaceable functions is |
* called. |
* - mbedtls_internal_ecp_free() must \b only be called when the alternative |
* implementation is activated. |
* - mbedtls_internal_ecp_init() must \b not be called when the alternative |
* implementation is activated. |
* - Public functions must not return while the alternative implementation is |
* activated. |
* - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and |
* before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) |
* \endcode ensures that the alternative implementation supports the current |
* group. |
*/ |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
#endif |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/ecp.h" |
#include "mbedtls/threading.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if !defined(MBEDTLS_ECP_ALT) |
/* Parameter validation macros based on platform_util.h */ |
#define ECP_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) |
#define ECP_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#include <stdio.h> |
#define mbedtls_printf printf |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/ecp_internal.h" |
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ |
!defined(inline) && !defined(__cplusplus) |
#define inline __inline |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* Counts of point addition and doubling, and field multiplications. |
* Used to test resistance of point multiplication to simple timing attacks. |
*/ |
static unsigned long add_count, dbl_count, mul_count; |
#endif |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* Maximum number of "basic operations" to be done in a row. |
* |
* Default value 0 means that ECC operations will not yield. |
* Note that regardless of the value of ecp_max_ops, always at |
* least one step is performed before yielding. |
* |
* Setting ecp_max_ops=1 can be suitable for testing purposes |
* as it will interrupt computation at all possible points. |
*/ |
static unsigned ecp_max_ops = 0; |
/* |
* Set ecp_max_ops |
*/ |
void mbedtls_ecp_set_max_ops( unsigned max_ops ) |
{ |
ecp_max_ops = max_ops; |
} |
/* |
* Check if restart is enabled |
*/ |
int mbedtls_ecp_restart_is_enabled( void ) |
{ |
return( ecp_max_ops != 0 ); |
} |
/* |
* Restart sub-context for ecp_mul_comb() |
*/ |
struct mbedtls_ecp_restart_mul |
{ |
mbedtls_ecp_point R; /* current intermediate result */ |
size_t i; /* current index in various loops, 0 outside */ |
mbedtls_ecp_point *T; /* table for precomputed points */ |
unsigned char T_size; /* number of points in table T */ |
enum { /* what were we doing last time we returned? */ |
ecp_rsm_init = 0, /* nothing so far, dummy initial state */ |
ecp_rsm_pre_dbl, /* precompute 2^n multiples */ |
ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ |
ecp_rsm_pre_add, /* precompute remaining points by adding */ |
ecp_rsm_pre_norm_add, /* normalize all precomputed points */ |
ecp_rsm_comb_core, /* ecp_mul_comb_core() */ |
ecp_rsm_final_norm, /* do the final normalization */ |
} state; |
}; |
/* |
* Init restart_mul sub-context |
*/ |
static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) |
{ |
mbedtls_ecp_point_init( &ctx->R ); |
ctx->i = 0; |
ctx->T = NULL; |
ctx->T_size = 0; |
ctx->state = ecp_rsm_init; |
} |
/* |
* Free the components of a restart_mul sub-context |
*/ |
static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) |
{ |
unsigned char i; |
if( ctx == NULL ) |
return; |
mbedtls_ecp_point_free( &ctx->R ); |
if( ctx->T != NULL ) |
{ |
for( i = 0; i < ctx->T_size; i++ ) |
mbedtls_ecp_point_free( ctx->T + i ); |
mbedtls_free( ctx->T ); |
} |
ecp_restart_rsm_init( ctx ); |
} |
/* |
* Restart context for ecp_muladd() |
*/ |
struct mbedtls_ecp_restart_muladd |
{ |
mbedtls_ecp_point mP; /* mP value */ |
mbedtls_ecp_point R; /* R intermediate result */ |
enum { /* what should we do next? */ |
ecp_rsma_mul1 = 0, /* first multiplication */ |
ecp_rsma_mul2, /* second multiplication */ |
ecp_rsma_add, /* addition */ |
ecp_rsma_norm, /* normalization */ |
} state; |
}; |
/* |
* Init restart_muladd sub-context |
*/ |
static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) |
{ |
mbedtls_ecp_point_init( &ctx->mP ); |
mbedtls_ecp_point_init( &ctx->R ); |
ctx->state = ecp_rsma_mul1; |
} |
/* |
* Free the components of a restart_muladd sub-context |
*/ |
static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_ecp_point_free( &ctx->mP ); |
mbedtls_ecp_point_free( &ctx->R ); |
ecp_restart_ma_init( ctx ); |
} |
/* |
* Initialize a restart context |
*/ |
void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) |
{ |
ECP_VALIDATE( ctx != NULL ); |
ctx->ops_done = 0; |
ctx->depth = 0; |
ctx->rsm = NULL; |
ctx->ma = NULL; |
} |
/* |
* Free the components of a restart context |
*/ |
void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) |
{ |
if( ctx == NULL ) |
return; |
ecp_restart_rsm_free( ctx->rsm ); |
mbedtls_free( ctx->rsm ); |
ecp_restart_ma_free( ctx->ma ); |
mbedtls_free( ctx->ma ); |
mbedtls_ecp_restart_init( ctx ); |
} |
/* |
* Check if we can do the next step |
*/ |
int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, |
mbedtls_ecp_restart_ctx *rs_ctx, |
unsigned ops ) |
{ |
ECP_VALIDATE_RET( grp != NULL ); |
if( rs_ctx != NULL && ecp_max_ops != 0 ) |
{ |
/* scale depending on curve size: the chosen reference is 256-bit, |
* and multiplication is quadratic. Round to the closest integer. */ |
if( grp->pbits >= 512 ) |
ops *= 4; |
else if( grp->pbits >= 384 ) |
ops *= 2; |
/* Avoid infinite loops: always allow first step. |
* Because of that, however, it's not generally true |
* that ops_done <= ecp_max_ops, so the check |
* ops_done > ecp_max_ops below is mandatory. */ |
if( ( rs_ctx->ops_done != 0 ) && |
( rs_ctx->ops_done > ecp_max_ops || |
ops > ecp_max_ops - rs_ctx->ops_done ) ) |
{ |
return( MBEDTLS_ERR_ECP_IN_PROGRESS ); |
} |
/* update running count */ |
rs_ctx->ops_done += ops; |
} |
return( 0 ); |
} |
/* Call this when entering a function that needs its own sub-context */ |
#define ECP_RS_ENTER( SUB ) do { \ |
/* reset ops count for this call if top-level */ \ |
if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ |
rs_ctx->ops_done = 0; \ |
\ |
/* set up our own sub-context if needed */ \ |
if( mbedtls_ecp_restart_is_enabled() && \ |
rs_ctx != NULL && rs_ctx->SUB == NULL ) \ |
{ \ |
rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ |
if( rs_ctx->SUB == NULL ) \ |
return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ |
\ |
ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ |
} \ |
} while( 0 ) |
/* Call this when leaving a function that needs its own sub-context */ |
#define ECP_RS_LEAVE( SUB ) do { \ |
/* clear our sub-context when not in progress (done or error) */ \ |
if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ |
ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ |
{ \ |
ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ |
mbedtls_free( rs_ctx->SUB ); \ |
rs_ctx->SUB = NULL; \ |
} \ |
\ |
if( rs_ctx != NULL ) \ |
rs_ctx->depth--; \ |
} while( 0 ) |
#else /* MBEDTLS_ECP_RESTARTABLE */ |
#define ECP_RS_ENTER( sub ) (void) rs_ctx; |
#define ECP_RS_LEAVE( sub ) (void) rs_ctx; |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
#define ECP_SHORTWEIERSTRASS |
#endif |
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) |
#define ECP_MONTGOMERY |
#endif |
/* |
* Curve types: internal for now, might be exposed later |
*/ |
typedef enum |
{ |
ECP_TYPE_NONE = 0, |
ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ |
ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ |
} ecp_curve_type; |
/* |
* List of supported curves: |
* - internal ID |
* - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) |
* - size in bits |
* - readable name |
* |
* Curves are listed in order: largest curves first, and for a given size, |
* fastest curves first. This provides the default order for the SSL module. |
* |
* Reminder: update profiles in x509_crt.c when adding a new curves! |
*/ |
static const mbedtls_ecp_curve_info ecp_supported_curves[] = |
{ |
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) |
{ MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) |
{ MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) |
{ MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) |
{ MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, |
#endif |
{ MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, |
}; |
#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ |
sizeof( ecp_supported_curves[0] ) |
static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; |
/* |
* List of supported curves and associated info |
*/ |
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) |
{ |
return( ecp_supported_curves ); |
} |
/* |
* List of supported curves, group ID only |
*/ |
const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) |
{ |
static int init_done = 0; |
if( ! init_done ) |
{ |
size_t i = 0; |
const mbedtls_ecp_curve_info *curve_info; |
for( curve_info = mbedtls_ecp_curve_list(); |
curve_info->grp_id != MBEDTLS_ECP_DP_NONE; |
curve_info++ ) |
{ |
ecp_supported_grp_id[i++] = curve_info->grp_id; |
} |
ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; |
init_done = 1; |
} |
return( ecp_supported_grp_id ); |
} |
/* |
* Get the curve info for the internal identifier |
*/ |
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) |
{ |
const mbedtls_ecp_curve_info *curve_info; |
for( curve_info = mbedtls_ecp_curve_list(); |
curve_info->grp_id != MBEDTLS_ECP_DP_NONE; |
curve_info++ ) |
{ |
if( curve_info->grp_id == grp_id ) |
return( curve_info ); |
} |
return( NULL ); |
} |
/* |
* Get the curve info from the TLS identifier |
*/ |
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) |
{ |
const mbedtls_ecp_curve_info *curve_info; |
for( curve_info = mbedtls_ecp_curve_list(); |
curve_info->grp_id != MBEDTLS_ECP_DP_NONE; |
curve_info++ ) |
{ |
if( curve_info->tls_id == tls_id ) |
return( curve_info ); |
} |
return( NULL ); |
} |
/* |
* Get the curve info from the name |
*/ |
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) |
{ |
const mbedtls_ecp_curve_info *curve_info; |
if( name == NULL ) |
return( NULL ); |
for( curve_info = mbedtls_ecp_curve_list(); |
curve_info->grp_id != MBEDTLS_ECP_DP_NONE; |
curve_info++ ) |
{ |
if( strcmp( curve_info->name, name ) == 0 ) |
return( curve_info ); |
} |
return( NULL ); |
} |
/* |
* Get the type of a curve |
*/ |
static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) |
{ |
if( grp->G.X.p == NULL ) |
return( ECP_TYPE_NONE ); |
if( grp->G.Y.p == NULL ) |
return( ECP_TYPE_MONTGOMERY ); |
else |
return( ECP_TYPE_SHORT_WEIERSTRASS ); |
} |
/* |
* Initialize (the components of) a point |
*/ |
void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) |
{ |
ECP_VALIDATE( pt != NULL ); |
mbedtls_mpi_init( &pt->X ); |
mbedtls_mpi_init( &pt->Y ); |
mbedtls_mpi_init( &pt->Z ); |
} |
/* |
* Initialize (the components of) a group |
*/ |
void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) |
{ |
ECP_VALIDATE( grp != NULL ); |
grp->id = MBEDTLS_ECP_DP_NONE; |
mbedtls_mpi_init( &grp->P ); |
mbedtls_mpi_init( &grp->A ); |
mbedtls_mpi_init( &grp->B ); |
mbedtls_ecp_point_init( &grp->G ); |
mbedtls_mpi_init( &grp->N ); |
grp->pbits = 0; |
grp->nbits = 0; |
grp->h = 0; |
grp->modp = NULL; |
grp->t_pre = NULL; |
grp->t_post = NULL; |
grp->t_data = NULL; |
grp->T = NULL; |
grp->T_size = 0; |
} |
/* |
* Initialize (the components of) a key pair |
*/ |
void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) |
{ |
ECP_VALIDATE( key != NULL ); |
mbedtls_ecp_group_init( &key->grp ); |
mbedtls_mpi_init( &key->d ); |
mbedtls_ecp_point_init( &key->Q ); |
} |
/* |
* Unallocate (the components of) a point |
*/ |
void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) |
{ |
if( pt == NULL ) |
return; |
mbedtls_mpi_free( &( pt->X ) ); |
mbedtls_mpi_free( &( pt->Y ) ); |
mbedtls_mpi_free( &( pt->Z ) ); |
} |
/* |
* Unallocate (the components of) a group |
*/ |
void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) |
{ |
size_t i; |
if( grp == NULL ) |
return; |
if( grp->h != 1 ) |
{ |
mbedtls_mpi_free( &grp->P ); |
mbedtls_mpi_free( &grp->A ); |
mbedtls_mpi_free( &grp->B ); |
mbedtls_ecp_point_free( &grp->G ); |
mbedtls_mpi_free( &grp->N ); |
} |
if( grp->T != NULL ) |
{ |
for( i = 0; i < grp->T_size; i++ ) |
mbedtls_ecp_point_free( &grp->T[i] ); |
mbedtls_free( grp->T ); |
} |
mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); |
} |
/* |
* Unallocate (the components of) a key pair |
*/ |
void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) |
{ |
if( key == NULL ) |
return; |
mbedtls_ecp_group_free( &key->grp ); |
mbedtls_mpi_free( &key->d ); |
mbedtls_ecp_point_free( &key->Q ); |
} |
/* |
* Copy the contents of a point |
*/ |
int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) |
{ |
int ret; |
ECP_VALIDATE_RET( P != NULL ); |
ECP_VALIDATE_RET( Q != NULL ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Copy the contents of a group object |
*/ |
int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) |
{ |
ECP_VALIDATE_RET( dst != NULL ); |
ECP_VALIDATE_RET( src != NULL ); |
return( mbedtls_ecp_group_load( dst, src->id ) ); |
} |
/* |
* Set point to zero |
*/ |
int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) |
{ |
int ret; |
ECP_VALIDATE_RET( pt != NULL ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Tell if a point is zero |
*/ |
int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) |
{ |
ECP_VALIDATE_RET( pt != NULL ); |
return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); |
} |
/* |
* Compare two points lazily |
*/ |
int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, |
const mbedtls_ecp_point *Q ) |
{ |
ECP_VALIDATE_RET( P != NULL ); |
ECP_VALIDATE_RET( Q != NULL ); |
if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && |
mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && |
mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) |
{ |
return( 0 ); |
} |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
/* |
* Import a non-zero point from ASCII strings |
*/ |
int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, |
const char *x, const char *y ) |
{ |
int ret; |
ECP_VALIDATE_RET( P != NULL ); |
ECP_VALIDATE_RET( x != NULL ); |
ECP_VALIDATE_RET( y != NULL ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Export a point into unsigned binary data (SEC1 2.3.3) |
*/ |
int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, |
const mbedtls_ecp_point *P, |
int format, size_t *olen, |
unsigned char *buf, size_t buflen ) |
{ |
int ret = 0; |
size_t plen; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( P != NULL ); |
ECP_VALIDATE_RET( olen != NULL ); |
ECP_VALIDATE_RET( buf != NULL ); |
ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || |
format == MBEDTLS_ECP_PF_COMPRESSED ); |
/* |
* Common case: P == 0 |
*/ |
if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) |
{ |
if( buflen < 1 ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
buf[0] = 0x00; |
*olen = 1; |
return( 0 ); |
} |
plen = mbedtls_mpi_size( &grp->P ); |
if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) |
{ |
*olen = 2 * plen + 1; |
if( buflen < *olen ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
buf[0] = 0x04; |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); |
} |
else if( format == MBEDTLS_ECP_PF_COMPRESSED ) |
{ |
*olen = plen + 1; |
if( buflen < *olen ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); |
} |
cleanup: |
return( ret ); |
} |
/* |
* Import a point from unsigned binary data (SEC1 2.3.4) |
*/ |
int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, |
mbedtls_ecp_point *pt, |
const unsigned char *buf, size_t ilen ) |
{ |
int ret; |
size_t plen; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( pt != NULL ); |
ECP_VALIDATE_RET( buf != NULL ); |
if( ilen < 1 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
if( buf[0] == 0x00 ) |
{ |
if( ilen == 1 ) |
return( mbedtls_ecp_set_zero( pt ) ); |
else |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
plen = mbedtls_mpi_size( &grp->P ); |
if( buf[0] != 0x04 ) |
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); |
if( ilen != 2 * plen + 1 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Import a point from a TLS ECPoint record (RFC 4492) |
* struct { |
* opaque point <1..2^8-1>; |
* } ECPoint; |
*/ |
int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, |
mbedtls_ecp_point *pt, |
const unsigned char **buf, size_t buf_len ) |
{ |
unsigned char data_len; |
const unsigned char *buf_start; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( pt != NULL ); |
ECP_VALIDATE_RET( buf != NULL ); |
ECP_VALIDATE_RET( *buf != NULL ); |
/* |
* We must have at least two bytes (1 for length, at least one for data) |
*/ |
if( buf_len < 2 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
data_len = *(*buf)++; |
if( data_len < 1 || data_len > buf_len - 1 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
/* |
* Save buffer start for read_binary and update buf |
*/ |
buf_start = *buf; |
*buf += data_len; |
return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) ); |
} |
/* |
* Export a point as a TLS ECPoint record (RFC 4492) |
* struct { |
* opaque point <1..2^8-1>; |
* } ECPoint; |
*/ |
int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, |
int format, size_t *olen, |
unsigned char *buf, size_t blen ) |
{ |
int ret; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( pt != NULL ); |
ECP_VALIDATE_RET( olen != NULL ); |
ECP_VALIDATE_RET( buf != NULL ); |
ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || |
format == MBEDTLS_ECP_PF_COMPRESSED ); |
/* |
* buffer length must be at least one, for our length byte |
*/ |
if( blen < 1 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, |
olen, buf + 1, blen - 1) ) != 0 ) |
return( ret ); |
/* |
* write length to the first byte and update total length |
*/ |
buf[0] = (unsigned char) *olen; |
++*olen; |
return( 0 ); |
} |
/* |
* Set a group from an ECParameters record (RFC 4492) |
*/ |
int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, |
const unsigned char **buf, size_t len ) |
{ |
int ret; |
mbedtls_ecp_group_id grp_id; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( buf != NULL ); |
ECP_VALIDATE_RET( *buf != NULL ); |
if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 ) |
return( ret ); |
return( mbedtls_ecp_group_load( grp, grp_id ) ); |
} |
/* |
* Read a group id from an ECParameters record (RFC 4492) and convert it to |
* mbedtls_ecp_group_id. |
*/ |
int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, |
const unsigned char **buf, size_t len ) |
{ |
uint16_t tls_id; |
const mbedtls_ecp_curve_info *curve_info; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( buf != NULL ); |
ECP_VALIDATE_RET( *buf != NULL ); |
/* |
* We expect at least three bytes (see below) |
*/ |
if( len < 3 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
/* |
* First byte is curve_type; only named_curve is handled |
*/ |
if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
/* |
* Next two bytes are the namedcurve value |
*/ |
tls_id = *(*buf)++; |
tls_id <<= 8; |
tls_id |= *(*buf)++; |
if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) |
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); |
*grp = curve_info->grp_id; |
return( 0 ); |
} |
/* |
* Write the ECParameters record corresponding to a group (RFC 4492) |
*/ |
int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, |
unsigned char *buf, size_t blen ) |
{ |
const mbedtls_ecp_curve_info *curve_info; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( buf != NULL ); |
ECP_VALIDATE_RET( olen != NULL ); |
if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
/* |
* We are going to write 3 bytes (see below) |
*/ |
*olen = 3; |
if( blen < *olen ) |
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
/* |
* First byte is curve_type, always named_curve |
*/ |
*buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; |
/* |
* Next two bytes are the namedcurve value |
*/ |
buf[0] = curve_info->tls_id >> 8; |
buf[1] = curve_info->tls_id & 0xFF; |
return( 0 ); |
} |
/* |
* Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. |
* See the documentation of struct mbedtls_ecp_group. |
* |
* This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. |
*/ |
static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) |
{ |
int ret; |
if( grp->modp == NULL ) |
return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); |
/* N->s < 0 is a much faster test, which fails only if N is 0 */ |
if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || |
mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) |
{ |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
MBEDTLS_MPI_CHK( grp->modp( N ) ); |
/* N->s < 0 is a much faster test, which fails only if N is 0 */ |
while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); |
while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) |
/* we known P, N and the result are positive */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Fast mod-p functions expect their argument to be in the 0..p^2 range. |
* |
* In order to guarantee that, we need to ensure that operands of |
* mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will |
* bring the result back to this range. |
* |
* The following macros are shortcuts for doing that. |
*/ |
/* |
* Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi |
*/ |
#if defined(MBEDTLS_SELF_TEST) |
#define INC_MUL_COUNT mul_count++; |
#else |
#define INC_MUL_COUNT |
#endif |
#define MOD_MUL( N ) \ |
do \ |
{ \ |
MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \ |
INC_MUL_COUNT \ |
} while( 0 ) |
/* |
* Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi |
* N->s < 0 is a very fast test, which fails only if N is 0 |
*/ |
#define MOD_SUB( N ) \ |
while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) ) |
/* |
* Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. |
* We known P, N and the result are positive, so sub_abs is correct, and |
* a bit faster. |
*/ |
#define MOD_ADD( N ) \ |
while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) ) |
#if defined(ECP_SHORTWEIERSTRASS) |
/* |
* For curves in short Weierstrass form, we do all the internal operations in |
* Jacobian coordinates. |
* |
* For multiplication, we'll use a comb method with coutermeasueres against |
* SPA, hence timing attacks. |
*/ |
/* |
* Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) |
* Cost: 1N := 1I + 3M + 1S |
*/ |
static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) |
{ |
int ret; |
mbedtls_mpi Zi, ZZi; |
if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) |
return( 0 ); |
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); |
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ |
mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); |
/* |
* X = X / Z^2 mod p |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); |
/* |
* Y = Y / Z^3 mod p |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); |
/* |
* Z = 1 |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); |
cleanup: |
mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); |
return( ret ); |
} |
/* |
* Normalize jacobian coordinates of an array of (pointers to) points, |
* using Montgomery's trick to perform only one inversion mod P. |
* (See for example Cohen's "A Course in Computational Algebraic Number |
* Theory", Algorithm 10.3.4.) |
* |
* Warning: fails (returning an error) if one of the points is zero! |
* This should never happen, see choice of w in ecp_mul_comb(). |
* |
* Cost: 1N(t) := 1I + (6t - 3)M + 1S |
*/ |
static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, |
mbedtls_ecp_point *T[], size_t T_size ) |
{ |
int ret; |
size_t i; |
mbedtls_mpi *c, u, Zi, ZZi; |
if( T_size < 2 ) |
return( ecp_normalize_jac( grp, *T ) ); |
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); |
#endif |
if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) |
return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); |
for( i = 0; i < T_size; i++ ) |
mbedtls_mpi_init( &c[i] ); |
mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); |
/* |
* c[i] = Z_0 * ... * Z_i |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); |
for( i = 1; i < T_size; i++ ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); |
MOD_MUL( c[i] ); |
} |
/* |
* u = 1 / (Z_0 * ... * Z_n) mod P |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); |
for( i = T_size - 1; ; i-- ) |
{ |
/* |
* Zi = 1 / Z_i mod p |
* u = 1 / (Z_0 * ... * Z_i) mod P |
*/ |
if( i == 0 ) { |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); |
} |
/* |
* proceed as in normalize() |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); |
/* |
* Post-precessing: reclaim some memory by shrinking coordinates |
* - not storing Z (always 1) |
* - shrinking other coordinates, but still keeping the same number of |
* limbs as P, as otherwise it will too likely be regrown too fast. |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); |
mbedtls_mpi_free( &T[i]->Z ); |
if( i == 0 ) |
break; |
} |
cleanup: |
mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); |
for( i = 0; i < T_size; i++ ) |
mbedtls_mpi_free( &c[i] ); |
mbedtls_free( c ); |
return( ret ); |
} |
/* |
* Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. |
* "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid |
*/ |
static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, |
mbedtls_ecp_point *Q, |
unsigned char inv ) |
{ |
int ret; |
unsigned char nonzero; |
mbedtls_mpi mQY; |
mbedtls_mpi_init( &mQY ); |
/* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); |
nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); |
cleanup: |
mbedtls_mpi_free( &mQY ); |
return( ret ); |
} |
/* |
* Point doubling R = 2 P, Jacobian coordinates |
* |
* Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . |
* |
* We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR |
* (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. |
* |
* Standard optimizations are applied when curve parameter A is one of { 0, -3 }. |
* |
* Cost: 1D := 3M + 4S (A == 0) |
* 4M + 4S (A == -3) |
* 3M + 6S + 1a otherwise |
*/ |
static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_ecp_point *P ) |
{ |
int ret; |
mbedtls_mpi M, S, T, U; |
#if defined(MBEDTLS_SELF_TEST) |
dbl_count++; |
#endif |
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); |
#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ |
mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); |
/* Special case for A = -3 */ |
if( grp->A.p == NULL ) |
{ |
/* M = 3(X + Z^2)(X - Z^2) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); |
} |
else |
{ |
/* M = 3.X^2 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); |
/* Optimize away for "koblitz" curves with A = 0 */ |
if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) |
{ |
/* M += A.Z^4 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); |
} |
} |
/* S = 4.X.Y^2 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); |
/* U = 8.Y^4 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); |
/* T = M^2 - 2.S */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); |
/* S = M(S - T) - U */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); |
/* U = 2.Y.Z */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); |
cleanup: |
mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); |
return( ret ); |
} |
/* |
* Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) |
* |
* The coordinates of Q must be normalized (= affine), |
* but those of P don't need to. R is not normalized. |
* |
* Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. |
* None of these cases can happen as intermediate step in ecp_mul_comb(): |
* - at each step, P, Q and R are multiples of the base point, the factor |
* being less than its order, so none of them is zero; |
* - Q is an odd multiple of the base point, P an even multiple, |
* due to the choice of precomputed points in the modified comb method. |
* So branches for these cases do not leak secret information. |
* |
* We accept Q->Z being unset (saving memory in tables) as meaning 1. |
* |
* Cost: 1A := 8M + 3S |
*/ |
static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) |
{ |
int ret; |
mbedtls_mpi T1, T2, T3, T4, X, Y, Z; |
#if defined(MBEDTLS_SELF_TEST) |
add_count++; |
#endif |
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); |
#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ |
/* |
* Trivial cases: P == 0 or Q == 0 (case 1) |
*/ |
if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) |
return( mbedtls_ecp_copy( R, Q ) ); |
if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) |
return( mbedtls_ecp_copy( R, P ) ); |
/* |
* Make sure Q coordinates are normalized |
*/ |
if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); |
mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); |
/* Special cases (2) and (3) */ |
if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) |
{ |
if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) |
{ |
ret = ecp_double_jac( grp, R, P ); |
goto cleanup; |
} |
else |
{ |
ret = mbedtls_ecp_set_zero( R ); |
goto cleanup; |
} |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); |
cleanup: |
mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); |
mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); |
return( ret ); |
} |
/* |
* Randomize jacobian coordinates: |
* (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l |
* This is sort of the reverse operation of ecp_normalize_jac(). |
* |
* This countermeasure was first suggested in [2]. |
*/ |
static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
int ret; |
mbedtls_mpi l, ll; |
size_t p_size; |
int count = 0; |
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); |
#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ |
p_size = ( grp->pbits + 7 ) / 8; |
mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); |
/* Generate l such that 1 < l < p */ |
do |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); |
while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); |
if( count++ > 10 ) |
return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); |
} |
while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); |
/* Z = l * Z */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); |
/* X = l^2 * X */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); |
/* Y = l^3 * Y */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); |
cleanup: |
mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); |
return( ret ); |
} |
/* |
* Check and define parameters used by the comb method (see below for details) |
*/ |
#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 |
#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" |
#endif |
/* d = ceil( n / w ) */ |
#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 |
/* number of precomputed points */ |
#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) |
/* |
* Compute the representation of m that will be used with our comb method. |
* |
* The basic comb method is described in GECC 3.44 for example. We use a |
* modified version that provides resistance to SPA by avoiding zero |
* digits in the representation as in [3]. We modify the method further by |
* requiring that all K_i be odd, which has the small cost that our |
* representation uses one more K_i, due to carries, but saves on the size of |
* the precomputed table. |
* |
* Summary of the comb method and its modifications: |
* |
* - The goal is to compute m*P for some w*d-bit integer m. |
* |
* - The basic comb method splits m into the w-bit integers |
* x[0] .. x[d-1] where x[i] consists of the bits in m whose |
* index has residue i modulo d, and computes m * P as |
* S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where |
* S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. |
* |
* - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by |
* .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., |
* thereby successively converting it into a form where all summands |
* are nonzero, at the cost of negative summands. This is the basic idea of [3]. |
* |
* - More generally, even if x[i+1] != 0, we can first transform the sum as |
* .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., |
* and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. |
* Performing and iterating this procedure for those x[i] that are even |
* (keeping track of carry), we can transform the original sum into one of the form |
* S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] |
* with all x'[i] odd. It is therefore only necessary to know S at odd indices, |
* which is why we are only computing half of it in the first place in |
* ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. |
* |
* - For the sake of compactness, only the seven low-order bits of x[i] |
* are used to represent its absolute value (K_i in the paper), and the msb |
* of x[i] encodes the sign (s_i in the paper): it is set if and only if |
* if s_i == -1; |
* |
* Calling conventions: |
* - x is an array of size d + 1 |
* - w is the size, ie number of teeth, of the comb, and must be between |
* 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) |
* - m is the MPI, expected to be odd and such that bitlength(m) <= w * d |
* (the result will be incorrect if these assumptions are not satisfied) |
*/ |
static void ecp_comb_recode_core( unsigned char x[], size_t d, |
unsigned char w, const mbedtls_mpi *m ) |
{ |
size_t i, j; |
unsigned char c, cc, adjust; |
memset( x, 0, d+1 ); |
/* First get the classical comb values (except for x_d = 0) */ |
for( i = 0; i < d; i++ ) |
for( j = 0; j < w; j++ ) |
x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; |
/* Now make sure x_1 .. x_d are odd */ |
c = 0; |
for( i = 1; i <= d; i++ ) |
{ |
/* Add carry and update it */ |
cc = x[i] & c; |
x[i] = x[i] ^ c; |
c = cc; |
/* Adjust if needed, avoiding branches */ |
adjust = 1 - ( x[i] & 0x01 ); |
c |= x[i] & ( x[i-1] * adjust ); |
x[i] = x[i] ^ ( x[i-1] * adjust ); |
x[i-1] |= adjust << 7; |
} |
} |
/* |
* Precompute points for the adapted comb method |
* |
* Assumption: T must be able to hold 2^{w - 1} elements. |
* |
* Operation: If i = i_{w-1} ... i_1 is the binary representation of i, |
* sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. |
* |
* Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) |
* |
* Note: Even comb values (those where P would be omitted from the |
* sum defining T[i] above) are not needed in our adaption |
* the comb method. See ecp_comb_recode_core(). |
* |
* This function currently works in four steps: |
* (1) [dbl] Computation of intermediate T[i] for 2-power values of i |
* (2) [norm_dbl] Normalization of coordinates of these T[i] |
* (3) [add] Computation of all T[i] |
* (4) [norm_add] Normalization of all T[i] |
* |
* Step 1 can be interrupted but not the others; together with the final |
* coordinate normalization they are the largest steps done at once, depending |
* on the window size. Here are operation counts for P-256: |
* |
* step (2) (3) (4) |
* w = 5 142 165 208 |
* w = 4 136 77 160 |
* w = 3 130 33 136 |
* w = 2 124 11 124 |
* |
* So if ECC operations are blocking for too long even with a low max_ops |
* value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order |
* to minimize maximum blocking time. |
*/ |
static int ecp_precompute_comb( const mbedtls_ecp_group *grp, |
mbedtls_ecp_point T[], const mbedtls_ecp_point *P, |
unsigned char w, size_t d, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
unsigned char i; |
size_t j = 0; |
const unsigned char T_size = 1U << ( w - 1 ); |
mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
{ |
if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) |
goto dbl; |
if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) |
goto norm_dbl; |
if( rs_ctx->rsm->state == ecp_rsm_pre_add ) |
goto add; |
if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) |
goto norm_add; |
} |
#else |
(void) rs_ctx; |
#endif |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
{ |
rs_ctx->rsm->state = ecp_rsm_pre_dbl; |
/* initial state for the loop */ |
rs_ctx->rsm->i = 0; |
} |
dbl: |
#endif |
/* |
* Set T[0] = P and |
* T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) |
*/ |
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) |
j = rs_ctx->rsm->i; |
else |
#endif |
j = 0; |
for( ; j < d * ( w - 1 ); j++ ) |
{ |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); |
i = 1U << ( j / d ); |
cur = T + i; |
if( j % d == 0 ) |
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); |
MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); |
} |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; |
norm_dbl: |
#endif |
/* |
* Normalize current elements in T. As T has holes, |
* use an auxiliary array of pointers to elements in T. |
*/ |
j = 0; |
for( i = 1; i < T_size; i <<= 1 ) |
TT[j++] = T + i; |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); |
MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
rs_ctx->rsm->state = ecp_rsm_pre_add; |
add: |
#endif |
/* |
* Compute the remaining ones using the minimal number of additions |
* Be careful to update T[2^l] only after using it! |
*/ |
MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); |
for( i = 1; i < T_size; i <<= 1 ) |
{ |
j = i; |
while( j-- ) |
MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); |
} |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
rs_ctx->rsm->state = ecp_rsm_pre_norm_add; |
norm_add: |
#endif |
/* |
* Normalize final elements in T. Even though there are no holes now, we |
* still need the auxiliary array for homogeneity with the previous |
* call. Also, skip T[0] which is already normalised, being a copy of P. |
*/ |
for( j = 0; j + 1 < T_size; j++ ) |
TT[j] = T + j + 1; |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); |
MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); |
cleanup: |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL && |
ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
{ |
if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) |
rs_ctx->rsm->i = j; |
} |
#endif |
return( ret ); |
} |
/* |
* Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] |
* |
* See ecp_comb_recode_core() for background |
*/ |
static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_ecp_point T[], unsigned char T_size, |
unsigned char i ) |
{ |
int ret; |
unsigned char ii, j; |
/* Ignore the "sign" bit and scale down */ |
ii = ( i & 0x7Fu ) >> 1; |
/* Read the whole table to thwart cache-based timing attacks */ |
for( j = 0; j < T_size; j++ ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); |
} |
/* Safely invert result if i is "negative" */ |
MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Core multiplication algorithm for the (modified) comb method. |
* This part is actually common with the basic comb method (GECC 3.44) |
* |
* Cost: d A + d D + 1 R |
*/ |
static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_ecp_point T[], unsigned char T_size, |
const unsigned char x[], size_t d, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_ecp_point Txi; |
size_t i; |
mbedtls_ecp_point_init( &Txi ); |
#if !defined(MBEDTLS_ECP_RESTARTABLE) |
(void) rs_ctx; |
#endif |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL && |
rs_ctx->rsm->state != ecp_rsm_comb_core ) |
{ |
rs_ctx->rsm->i = 0; |
rs_ctx->rsm->state = ecp_rsm_comb_core; |
} |
/* new 'if' instead of nested for the sake of the 'else' branch */ |
if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) |
{ |
/* restore current index (R already pointing to rs_ctx->rsm->R) */ |
i = rs_ctx->rsm->i; |
} |
else |
#endif |
{ |
/* Start with a non-zero point and randomize its coordinates */ |
i = d; |
MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); |
if( f_rng != 0 ) |
MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); |
} |
while( i != 0 ) |
{ |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); |
--i; |
MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); |
MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); |
MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); |
} |
cleanup: |
mbedtls_ecp_point_free( &Txi ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL && |
ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
{ |
rs_ctx->rsm->i = i; |
/* no need to save R, already pointing to rs_ctx->rsm->R */ |
} |
#endif |
return( ret ); |
} |
/* |
* Recode the scalar to get constant-time comb multiplication |
* |
* As the actual scalar recoding needs an odd scalar as a starting point, |
* this wrapper ensures that by replacing m by N - m if necessary, and |
* informs the caller that the result of multiplication will be negated. |
* |
* This works because we only support large prime order for Short Weierstrass |
* curves, so N is always odd hence either m or N - m is. |
* |
* See ecp_comb_recode_core() for background. |
*/ |
static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, |
const mbedtls_mpi *m, |
unsigned char k[COMB_MAX_D + 1], |
size_t d, |
unsigned char w, |
unsigned char *parity_trick ) |
{ |
int ret; |
mbedtls_mpi M, mm; |
mbedtls_mpi_init( &M ); |
mbedtls_mpi_init( &mm ); |
/* N is always odd (see above), just make extra sure */ |
if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
/* do we need the parity trick? */ |
*parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); |
/* execute parity fix in constant time */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); |
/* actual scalar recoding */ |
ecp_comb_recode_core( k, d, w, &M ); |
cleanup: |
mbedtls_mpi_free( &mm ); |
mbedtls_mpi_free( &M ); |
return( ret ); |
} |
/* |
* Perform comb multiplication (for short Weierstrass curves) |
* once the auxiliary table has been pre-computed. |
* |
* Scalar recoding may use a parity trick that makes us compute -m * P, |
* if that is the case we'll need to recover m * P at the end. |
*/ |
static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, |
mbedtls_ecp_point *R, |
const mbedtls_mpi *m, |
const mbedtls_ecp_point *T, |
unsigned char T_size, |
unsigned char w, |
size_t d, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
unsigned char parity_trick; |
unsigned char k[COMB_MAX_D + 1]; |
mbedtls_ecp_point *RR = R; |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
{ |
RR = &rs_ctx->rsm->R; |
if( rs_ctx->rsm->state == ecp_rsm_final_norm ) |
goto final_norm; |
} |
#endif |
MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, |
&parity_trick ) ); |
MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, |
f_rng, p_rng, rs_ctx ) ); |
MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
rs_ctx->rsm->state = ecp_rsm_final_norm; |
final_norm: |
#endif |
/* |
* Knowledge of the jacobian coordinates may leak the last few bits of the |
* scalar [1], and since our MPI implementation isn't constant-flow, |
* inversion (used for coordinate normalization) may leak the full value |
* of its input via side-channels [2]. |
* |
* [1] https://eprint.iacr.org/2003/191 |
* [2] https://eprint.iacr.org/2020/055 |
* |
* Avoid the leak by randomizing coordinates before we normalize them. |
*/ |
if( f_rng != 0 ) |
MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); |
MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); |
#endif |
cleanup: |
return( ret ); |
} |
/* |
* Pick window size based on curve size and whether we optimize for base point |
*/ |
static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, |
unsigned char p_eq_g ) |
{ |
unsigned char w; |
/* |
* Minimize the number of multiplications, that is minimize |
* 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) |
* (see costs of the various parts, with 1S = 1M) |
*/ |
w = grp->nbits >= 384 ? 5 : 4; |
/* |
* If P == G, pre-compute a bit more, since this may be re-used later. |
* Just adding one avoids upping the cost of the first mul too much, |
* and the memory cost too. |
*/ |
if( p_eq_g ) |
w++; |
/* |
* Make sure w is within bounds. |
* (The last test is useful only for very small curves in the test suite.) |
*/ |
if( w > MBEDTLS_ECP_WINDOW_SIZE ) |
w = MBEDTLS_ECP_WINDOW_SIZE; |
if( w >= grp->nbits ) |
w = 2; |
return( w ); |
} |
/* |
* Multiplication using the comb method - for curves in short Weierstrass form |
* |
* This function is mainly responsible for administrative work: |
* - managing the restart context if enabled |
* - managing the table of precomputed points (passed between the below two |
* functions): allocation, computation, ownership tranfer, freeing. |
* |
* It delegates the actual arithmetic work to: |
* ecp_precompute_comb() and ecp_mul_comb_with_precomp() |
* |
* See comments on ecp_comb_recode_core() regarding the computation strategy. |
*/ |
static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_mpi *m, const mbedtls_ecp_point *P, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
unsigned char w, p_eq_g, i; |
size_t d; |
unsigned char T_size, T_ok; |
mbedtls_ecp_point *T; |
ECP_RS_ENTER( rsm ); |
/* Is P the base point ? */ |
#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 |
p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && |
mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); |
#else |
p_eq_g = 0; |
#endif |
/* Pick window size and deduce related sizes */ |
w = ecp_pick_window_size( grp, p_eq_g ); |
T_size = 1U << ( w - 1 ); |
d = ( grp->nbits + w - 1 ) / w; |
/* Pre-computed table: do we have it already for the base point? */ |
if( p_eq_g && grp->T != NULL ) |
{ |
/* second pointer to the same table, will be deleted on exit */ |
T = grp->T; |
T_ok = 1; |
} |
else |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* Pre-computed table: do we have one in progress? complete? */ |
if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) |
{ |
/* transfer ownership of T from rsm to local function */ |
T = rs_ctx->rsm->T; |
rs_ctx->rsm->T = NULL; |
rs_ctx->rsm->T_size = 0; |
/* This effectively jumps to the call to mul_comb_after_precomp() */ |
T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; |
} |
else |
#endif |
/* Allocate table if we didn't have any */ |
{ |
T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); |
if( T == NULL ) |
{ |
ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; |
goto cleanup; |
} |
for( i = 0; i < T_size; i++ ) |
mbedtls_ecp_point_init( &T[i] ); |
T_ok = 0; |
} |
/* Compute table (or finish computing it) if not done already */ |
if( !T_ok ) |
{ |
MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); |
if( p_eq_g ) |
{ |
/* almost transfer ownership of T to the group, but keep a copy of |
* the pointer to use for calling the next function more easily */ |
grp->T = T; |
grp->T_size = T_size; |
} |
} |
/* Actual comb multiplication using precomputed points */ |
MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, |
T, T_size, w, d, |
f_rng, p_rng, rs_ctx ) ); |
cleanup: |
/* does T belong to the group? */ |
if( T == grp->T ) |
T = NULL; |
/* does T belong to the restart context? */ |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) |
{ |
/* transfer ownership of T from local function to rsm */ |
rs_ctx->rsm->T_size = T_size; |
rs_ctx->rsm->T = T; |
T = NULL; |
} |
#endif |
/* did T belong to us? then let's destroy it! */ |
if( T != NULL ) |
{ |
for( i = 0; i < T_size; i++ ) |
mbedtls_ecp_point_free( &T[i] ); |
mbedtls_free( T ); |
} |
/* don't free R while in progress in case R == P */ |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) |
#endif |
/* prevent caller from using invalid value */ |
if( ret != 0 ) |
mbedtls_ecp_point_free( R ); |
ECP_RS_LEAVE( rsm ); |
return( ret ); |
} |
#endif /* ECP_SHORTWEIERSTRASS */ |
#if defined(ECP_MONTGOMERY) |
/* |
* For Montgomery curves, we do all the internal arithmetic in projective |
* coordinates. Import/export of points uses only the x coordinates, which is |
* internaly represented as X / Z. |
* |
* For scalar multiplication, we'll use a Montgomery ladder. |
*/ |
/* |
* Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 |
* Cost: 1M + 1I |
*/ |
static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) |
{ |
int ret; |
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); |
#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Randomize projective x/z coordinates: |
* (X, Z) -> (l X, l Z) for random l |
* This is sort of the reverse operation of ecp_normalize_mxz(). |
* |
* This countermeasure was first suggested in [2]. |
* Cost: 2M |
*/ |
static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
int ret; |
mbedtls_mpi l; |
size_t p_size; |
int count = 0; |
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); |
#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ |
p_size = ( grp->pbits + 7 ) / 8; |
mbedtls_mpi_init( &l ); |
/* Generate l such that 1 < l < p */ |
do |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); |
while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); |
if( count++ > 10 ) |
return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); |
} |
while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); |
cleanup: |
mbedtls_mpi_free( &l ); |
return( ret ); |
} |
/* |
* Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), |
* for Montgomery curves in x/z coordinates. |
* |
* http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 |
* with |
* d = X1 |
* P = (X2, Z2) |
* Q = (X3, Z3) |
* R = (X4, Z4) |
* S = (X5, Z5) |
* and eliminating temporary variables tO, ..., t4. |
* |
* Cost: 5M + 4S |
*/ |
static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, |
mbedtls_ecp_point *R, mbedtls_ecp_point *S, |
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, |
const mbedtls_mpi *d ) |
{ |
int ret; |
mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; |
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) |
if( mbedtls_internal_ecp_grp_capable( grp ) ) |
return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); |
#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ |
mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); |
mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); |
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); |
cleanup: |
mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); |
mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); |
mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); |
return( ret ); |
} |
/* |
* Multiplication with Montgomery ladder in x/z coordinates, |
* for curves in Montgomery form |
*/ |
static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_mpi *m, const mbedtls_ecp_point *P, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
size_t i; |
unsigned char b; |
mbedtls_ecp_point RP; |
mbedtls_mpi PX; |
mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); |
/* Save PX and read from P before writing to R, in case P == R */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); |
/* Set R to zero in modified x/z coordinates */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); |
mbedtls_mpi_free( &R->Y ); |
/* RP.X might be sligtly larger than P, so reduce it */ |
MOD_ADD( RP.X ); |
/* Randomize coordinates of the starting point */ |
if( f_rng != NULL ) |
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); |
/* Loop invariant: R = result so far, RP = R + P */ |
i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ |
while( i-- > 0 ) |
{ |
b = mbedtls_mpi_get_bit( m, i ); |
/* |
* if (b) R = 2R + P else R = 2R, |
* which is: |
* if (b) double_add( RP, R, RP, R ) |
* else double_add( R, RP, R, RP ) |
* but using safe conditional swaps to avoid leaks |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); |
MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); |
} |
/* |
* Knowledge of the projective coordinates may leak the last few bits of the |
* scalar [1], and since our MPI implementation isn't constant-flow, |
* inversion (used for coordinate normalization) may leak the full value |
* of its input via side-channels [2]. |
* |
* [1] https://eprint.iacr.org/2003/191 |
* [2] https://eprint.iacr.org/2020/055 |
* |
* Avoid the leak by randomizing coordinates before we normalize them. |
*/ |
if( f_rng != NULL ) |
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); |
cleanup: |
mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); |
return( ret ); |
} |
#endif /* ECP_MONTGOMERY */ |
/* |
* Restartable multiplication R = m * P |
*/ |
int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_mpi *m, const mbedtls_ecp_point *P, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
char is_grp_capable = 0; |
#endif |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( R != NULL ); |
ECP_VALIDATE_RET( m != NULL ); |
ECP_VALIDATE_RET( P != NULL ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* reset ops count for this call if top-level */ |
if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) |
rs_ctx->ops_done = 0; |
#endif |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) |
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); |
#endif /* MBEDTLS_ECP_INTERNAL_ALT */ |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* skip argument check when restarting */ |
if( rs_ctx == NULL || rs_ctx->rsm == NULL ) |
#endif |
{ |
/* check_privkey is free */ |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); |
/* Common sanity checks */ |
MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); |
} |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
#if defined(ECP_MONTGOMERY) |
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) |
MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); |
#endif |
#if defined(ECP_SHORTWEIERSTRASS) |
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) |
MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); |
#endif |
cleanup: |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
if( is_grp_capable ) |
mbedtls_internal_ecp_free( grp ); |
#endif /* MBEDTLS_ECP_INTERNAL_ALT */ |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL ) |
rs_ctx->depth--; |
#endif |
return( ret ); |
} |
/* |
* Multiplication R = m * P |
*/ |
int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_mpi *m, const mbedtls_ecp_point *P, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( R != NULL ); |
ECP_VALIDATE_RET( m != NULL ); |
ECP_VALIDATE_RET( P != NULL ); |
return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); |
} |
#if defined(ECP_SHORTWEIERSTRASS) |
/* |
* Check that an affine point is valid as a public key, |
* short weierstrass curves (SEC1 3.2.3.1) |
*/ |
static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) |
{ |
int ret; |
mbedtls_mpi YY, RHS; |
/* pt coordinates must be normalized for our checks */ |
if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || |
mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || |
mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || |
mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) |
return( MBEDTLS_ERR_ECP_INVALID_KEY ); |
mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); |
/* |
* YY = Y^2 |
* RHS = X (X^2 + A) + B = X^3 + A X + B |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); |
/* Special case for A = -3 */ |
if( grp->A.p == NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); |
if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) |
ret = MBEDTLS_ERR_ECP_INVALID_KEY; |
cleanup: |
mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); |
return( ret ); |
} |
#endif /* ECP_SHORTWEIERSTRASS */ |
/* |
* R = m * P with shortcuts for m == 1 and m == -1 |
* NOT constant-time - ONLY for short Weierstrass! |
*/ |
static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, |
mbedtls_ecp_point *R, |
const mbedtls_mpi *m, |
const mbedtls_ecp_point *P, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); |
} |
else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); |
if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); |
} |
else |
{ |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P, |
NULL, NULL, rs_ctx ) ); |
} |
cleanup: |
return( ret ); |
} |
/* |
* Restartable linear combination |
* NOT constant-time |
*/ |
int mbedtls_ecp_muladd_restartable( |
mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_mpi *m, const mbedtls_ecp_point *P, |
const mbedtls_mpi *n, const mbedtls_ecp_point *Q, |
mbedtls_ecp_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_ecp_point mP; |
mbedtls_ecp_point *pmP = &mP; |
mbedtls_ecp_point *pR = R; |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
char is_grp_capable = 0; |
#endif |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( R != NULL ); |
ECP_VALIDATE_RET( m != NULL ); |
ECP_VALIDATE_RET( P != NULL ); |
ECP_VALIDATE_RET( n != NULL ); |
ECP_VALIDATE_RET( Q != NULL ); |
if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) |
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); |
mbedtls_ecp_point_init( &mP ); |
ECP_RS_ENTER( ma ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->ma != NULL ) |
{ |
/* redirect intermediate results to restart context */ |
pmP = &rs_ctx->ma->mP; |
pR = &rs_ctx->ma->R; |
/* jump to next operation */ |
if( rs_ctx->ma->state == ecp_rsma_mul2 ) |
goto mul2; |
if( rs_ctx->ma->state == ecp_rsma_add ) |
goto add; |
if( rs_ctx->ma->state == ecp_rsma_norm ) |
goto norm; |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->ma != NULL ) |
rs_ctx->ma->state = ecp_rsma_mul2; |
mul2: |
#endif |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) |
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); |
#endif /* MBEDTLS_ECP_INTERNAL_ALT */ |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->ma != NULL ) |
rs_ctx->ma->state = ecp_rsma_add; |
add: |
#endif |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); |
MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->ma != NULL ) |
rs_ctx->ma->state = ecp_rsma_norm; |
norm: |
#endif |
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); |
MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && rs_ctx->ma != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); |
#endif |
cleanup: |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
if( is_grp_capable ) |
mbedtls_internal_ecp_free( grp ); |
#endif /* MBEDTLS_ECP_INTERNAL_ALT */ |
mbedtls_ecp_point_free( &mP ); |
ECP_RS_LEAVE( ma ); |
return( ret ); |
} |
/* |
* Linear combination |
* NOT constant-time |
*/ |
int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, |
const mbedtls_mpi *m, const mbedtls_ecp_point *P, |
const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) |
{ |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( R != NULL ); |
ECP_VALIDATE_RET( m != NULL ); |
ECP_VALIDATE_RET( P != NULL ); |
ECP_VALIDATE_RET( n != NULL ); |
ECP_VALIDATE_RET( Q != NULL ); |
return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); |
} |
#if defined(ECP_MONTGOMERY) |
/* |
* Check validity of a public key for Montgomery curves with x-only schemes |
*/ |
static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) |
{ |
/* [Curve25519 p. 5] Just check X is the correct number of bytes */ |
/* Allow any public value, if it's too big then we'll just reduce it mod p |
* (RFC 7748 sec. 5 para. 3). */ |
if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) |
return( MBEDTLS_ERR_ECP_INVALID_KEY ); |
return( 0 ); |
} |
#endif /* ECP_MONTGOMERY */ |
/* |
* Check that a point is valid as a public key |
*/ |
int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, |
const mbedtls_ecp_point *pt ) |
{ |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( pt != NULL ); |
/* Must use affine coordinates */ |
if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) |
return( MBEDTLS_ERR_ECP_INVALID_KEY ); |
#if defined(ECP_MONTGOMERY) |
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) |
return( ecp_check_pubkey_mx( grp, pt ) ); |
#endif |
#if defined(ECP_SHORTWEIERSTRASS) |
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) |
return( ecp_check_pubkey_sw( grp, pt ) ); |
#endif |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
/* |
* Check that an mbedtls_mpi is valid as a private key |
*/ |
int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, |
const mbedtls_mpi *d ) |
{ |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( d != NULL ); |
#if defined(ECP_MONTGOMERY) |
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) |
{ |
/* see RFC 7748 sec. 5 para. 5 */ |
if( mbedtls_mpi_get_bit( d, 0 ) != 0 || |
mbedtls_mpi_get_bit( d, 1 ) != 0 || |
mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ |
return( MBEDTLS_ERR_ECP_INVALID_KEY ); |
/* see [Curve25519] page 5 */ |
if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) |
return( MBEDTLS_ERR_ECP_INVALID_KEY ); |
return( 0 ); |
} |
#endif /* ECP_MONTGOMERY */ |
#if defined(ECP_SHORTWEIERSTRASS) |
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) |
{ |
/* see SEC1 3.2 */ |
if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || |
mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) |
return( MBEDTLS_ERR_ECP_INVALID_KEY ); |
else |
return( 0 ); |
} |
#endif /* ECP_SHORTWEIERSTRASS */ |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
/* |
* Generate a private key |
*/ |
int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, |
mbedtls_mpi *d, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
size_t n_size; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( d != NULL ); |
ECP_VALIDATE_RET( f_rng != NULL ); |
n_size = ( grp->nbits + 7 ) / 8; |
#if defined(ECP_MONTGOMERY) |
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) |
{ |
/* [M225] page 5 */ |
size_t b; |
do { |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); |
} while( mbedtls_mpi_bitlen( d ) == 0); |
/* Make sure the most significant bit is nbits */ |
b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ |
if( b > grp->nbits ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); |
else |
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); |
/* Make sure the last two bits are unset for Curve448, three bits for |
Curve25519 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); |
if( grp->nbits == 254 ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); |
} |
} |
#endif /* ECP_MONTGOMERY */ |
#if defined(ECP_SHORTWEIERSTRASS) |
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) |
{ |
/* SEC1 3.2.1: Generate d such that 1 <= n < N */ |
int count = 0; |
unsigned cmp = 0; |
/* |
* Match the procedure given in RFC 6979 (deterministic ECDSA): |
* - use the same byte ordering; |
* - keep the leftmost nbits bits of the generated octet string; |
* - try until result is in the desired range. |
* This also avoids any biais, which is especially important for ECDSA. |
*/ |
do |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); |
/* |
* Each try has at worst a probability 1/2 of failing (the msb has |
* a probability 1/2 of being 0, and then the result will be < N), |
* so after 30 tries failure probability is a most 2**(-30). |
* |
* For most curves, 1 try is enough with overwhelming probability, |
* since N starts with a lot of 1s in binary, but some curves |
* such as secp224k1 are actually very close to the worst case. |
*/ |
if( ++count > 30 ) |
return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); |
ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp ); |
if( ret != 0 ) |
{ |
goto cleanup; |
} |
} |
while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 ); |
} |
#endif /* ECP_SHORTWEIERSTRASS */ |
cleanup: |
return( ret ); |
} |
/* |
* Generate a keypair with configurable base point |
*/ |
int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, |
const mbedtls_ecp_point *G, |
mbedtls_mpi *d, mbedtls_ecp_point *Q, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( d != NULL ); |
ECP_VALIDATE_RET( G != NULL ); |
ECP_VALIDATE_RET( Q != NULL ); |
ECP_VALIDATE_RET( f_rng != NULL ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Generate key pair, wrapper for conventional base point |
*/ |
int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, |
mbedtls_mpi *d, mbedtls_ecp_point *Q, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
ECP_VALIDATE_RET( grp != NULL ); |
ECP_VALIDATE_RET( d != NULL ); |
ECP_VALIDATE_RET( Q != NULL ); |
ECP_VALIDATE_RET( f_rng != NULL ); |
return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); |
} |
/* |
* Generate a keypair, prettier wrapper |
*/ |
int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
int ret; |
ECP_VALIDATE_RET( key != NULL ); |
ECP_VALIDATE_RET( f_rng != NULL ); |
if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) |
return( ret ); |
return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); |
} |
/* |
* Check a public-private key pair |
*/ |
int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) |
{ |
int ret; |
mbedtls_ecp_point Q; |
mbedtls_ecp_group grp; |
ECP_VALIDATE_RET( pub != NULL ); |
ECP_VALIDATE_RET( prv != NULL ); |
if( pub->grp.id == MBEDTLS_ECP_DP_NONE || |
pub->grp.id != prv->grp.id || |
mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || |
mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || |
mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) |
{ |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
} |
mbedtls_ecp_point_init( &Q ); |
mbedtls_ecp_group_init( &grp ); |
/* mbedtls_ecp_mul() needs a non-const group... */ |
mbedtls_ecp_group_copy( &grp, &prv->grp ); |
/* Also checks d is valid */ |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); |
if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || |
mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || |
mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) |
{ |
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
goto cleanup; |
} |
cleanup: |
mbedtls_ecp_point_free( &Q ); |
mbedtls_ecp_group_free( &grp ); |
return( ret ); |
} |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* Checkup routine |
*/ |
int mbedtls_ecp_self_test( int verbose ) |
{ |
int ret; |
size_t i; |
mbedtls_ecp_group grp; |
mbedtls_ecp_point R, P; |
mbedtls_mpi m; |
unsigned long add_c_prev, dbl_c_prev, mul_c_prev; |
/* exponents especially adapted for secp192r1 */ |
const char *exponents[] = |
{ |
"000000000000000000000000000000000000000000000001", /* one */ |
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ |
"5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ |
"400000000000000000000000000000000000000000000000", /* one and zeros */ |
"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ |
"555555555555555555555555555555555555555555555555", /* 101010... */ |
}; |
mbedtls_ecp_group_init( &grp ); |
mbedtls_ecp_point_init( &R ); |
mbedtls_ecp_point_init( &P ); |
mbedtls_mpi_init( &m ); |
/* Use secp192r1 if available, or any available curve */ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); |
#else |
MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); |
#endif |
if( verbose != 0 ) |
mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); |
/* Do a dummy multiplication first to trigger precomputation */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); |
add_count = 0; |
dbl_count = 0; |
mul_count = 0; |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); |
for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) |
{ |
add_c_prev = add_count; |
dbl_c_prev = dbl_count; |
mul_c_prev = mul_count; |
add_count = 0; |
dbl_count = 0; |
mul_count = 0; |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); |
if( add_count != add_c_prev || |
dbl_count != dbl_c_prev || |
mul_count != mul_c_prev ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed (%u)\n", (unsigned int) i ); |
ret = 1; |
goto cleanup; |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); |
/* We computed P = 2G last time, use it */ |
add_count = 0; |
dbl_count = 0; |
mul_count = 0; |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); |
for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) |
{ |
add_c_prev = add_count; |
dbl_c_prev = dbl_count; |
mul_c_prev = mul_count; |
add_count = 0; |
dbl_count = 0; |
mul_count = 0; |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); |
if( add_count != add_c_prev || |
dbl_count != dbl_c_prev || |
mul_count != mul_c_prev ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed (%u)\n", (unsigned int) i ); |
ret = 1; |
goto cleanup; |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
cleanup: |
if( ret < 0 && verbose != 0 ) |
mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); |
mbedtls_ecp_group_free( &grp ); |
mbedtls_ecp_point_free( &R ); |
mbedtls_ecp_point_free( &P ); |
mbedtls_mpi_free( &m ); |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* !MBEDTLS_ECP_ALT */ |
#endif /* MBEDTLS_ECP_C */ |
/programs/develop/libraries/kos_mbedtls/library/ecp_curves.c |
---|
0,0 → 1,1472 |
/* |
* Elliptic curves over GF(p): curve-specific data and functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/ecp.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if !defined(MBEDTLS_ECP_ALT) |
/* Parameter validation macros based on platform_util.h */ |
#define ECP_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) |
#define ECP_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ |
!defined(inline) && !defined(__cplusplus) |
#define inline __inline |
#endif |
/* |
* Conversion macros for embedded constants: |
* build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 |
*/ |
#if defined(MBEDTLS_HAVE_INT32) |
#define BYTES_TO_T_UINT_4( a, b, c, d ) \ |
( (mbedtls_mpi_uint) (a) << 0 ) | \ |
( (mbedtls_mpi_uint) (b) << 8 ) | \ |
( (mbedtls_mpi_uint) (c) << 16 ) | \ |
( (mbedtls_mpi_uint) (d) << 24 ) |
#define BYTES_TO_T_UINT_2( a, b ) \ |
BYTES_TO_T_UINT_4( a, b, 0, 0 ) |
#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ |
BYTES_TO_T_UINT_4( a, b, c, d ), \ |
BYTES_TO_T_UINT_4( e, f, g, h ) |
#else /* 64-bits */ |
#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ |
( (mbedtls_mpi_uint) (a) << 0 ) | \ |
( (mbedtls_mpi_uint) (b) << 8 ) | \ |
( (mbedtls_mpi_uint) (c) << 16 ) | \ |
( (mbedtls_mpi_uint) (d) << 24 ) | \ |
( (mbedtls_mpi_uint) (e) << 32 ) | \ |
( (mbedtls_mpi_uint) (f) << 40 ) | \ |
( (mbedtls_mpi_uint) (g) << 48 ) | \ |
( (mbedtls_mpi_uint) (h) << 56 ) |
#define BYTES_TO_T_UINT_4( a, b, c, d ) \ |
BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) |
#define BYTES_TO_T_UINT_2( a, b ) \ |
BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) |
#endif /* bits in mbedtls_mpi_uint */ |
/* |
* Note: the constants are in little-endian order |
* to be directly usable in MPIs |
*/ |
/* |
* Domain parameters for secp192r1 |
*/ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
static const mbedtls_mpi_uint secp192r1_p[] = { |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
static const mbedtls_mpi_uint secp192r1_b[] = { |
BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), |
BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), |
BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), |
}; |
static const mbedtls_mpi_uint secp192r1_gx[] = { |
BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), |
BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), |
BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), |
}; |
static const mbedtls_mpi_uint secp192r1_gy[] = { |
BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), |
BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), |
BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), |
}; |
static const mbedtls_mpi_uint secp192r1_n[] = { |
BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), |
BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ |
/* |
* Domain parameters for secp224r1 |
*/ |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) |
static const mbedtls_mpi_uint secp224r1_p[] = { |
BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), |
BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp224r1_b[] = { |
BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), |
BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), |
BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), |
BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), |
}; |
static const mbedtls_mpi_uint secp224r1_gx[] = { |
BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), |
BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), |
BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), |
BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), |
}; |
static const mbedtls_mpi_uint secp224r1_gy[] = { |
BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), |
BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), |
BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), |
BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), |
}; |
static const mbedtls_mpi_uint secp224r1_n[] = { |
BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), |
BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ |
/* |
* Domain parameters for secp256r1 |
*/ |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
static const mbedtls_mpi_uint secp256r1_p[] = { |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), |
BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), |
BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
static const mbedtls_mpi_uint secp256r1_b[] = { |
BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), |
BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), |
BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), |
BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), |
}; |
static const mbedtls_mpi_uint secp256r1_gx[] = { |
BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), |
BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), |
BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), |
BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), |
}; |
static const mbedtls_mpi_uint secp256r1_gy[] = { |
BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), |
BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), |
BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), |
BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), |
}; |
static const mbedtls_mpi_uint secp256r1_n[] = { |
BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), |
BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ |
/* |
* Domain parameters for secp384r1 |
*/ |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
static const mbedtls_mpi_uint secp384r1_p[] = { |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), |
BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
static const mbedtls_mpi_uint secp384r1_b[] = { |
BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), |
BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), |
BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), |
BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), |
BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), |
BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), |
}; |
static const mbedtls_mpi_uint secp384r1_gx[] = { |
BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), |
BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), |
BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), |
BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), |
BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), |
BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), |
}; |
static const mbedtls_mpi_uint secp384r1_gy[] = { |
BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), |
BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), |
BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), |
BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), |
BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), |
BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), |
}; |
static const mbedtls_mpi_uint secp384r1_n[] = { |
BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), |
BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), |
BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ |
/* |
* Domain parameters for secp521r1 |
*/ |
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) |
static const mbedtls_mpi_uint secp521r1_p[] = { |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_2( 0xFF, 0x01 ), |
}; |
static const mbedtls_mpi_uint secp521r1_b[] = { |
BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), |
BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), |
BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), |
BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), |
BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), |
BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), |
BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), |
BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), |
BYTES_TO_T_UINT_2( 0x51, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp521r1_gx[] = { |
BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), |
BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), |
BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), |
BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), |
BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), |
BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), |
BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), |
BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), |
BYTES_TO_T_UINT_2( 0xC6, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp521r1_gy[] = { |
BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), |
BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), |
BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), |
BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), |
BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), |
BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), |
BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), |
BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), |
BYTES_TO_T_UINT_2( 0x18, 0x01 ), |
}; |
static const mbedtls_mpi_uint secp521r1_n[] = { |
BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), |
BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), |
BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), |
BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), |
BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_2( 0xFF, 0x01 ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) |
static const mbedtls_mpi_uint secp192k1_p[] = { |
BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
static const mbedtls_mpi_uint secp192k1_a[] = { |
BYTES_TO_T_UINT_2( 0x00, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp192k1_b[] = { |
BYTES_TO_T_UINT_2( 0x03, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp192k1_gx[] = { |
BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), |
BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), |
BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), |
}; |
static const mbedtls_mpi_uint secp192k1_gy[] = { |
BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), |
BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), |
BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), |
}; |
static const mbedtls_mpi_uint secp192k1_n[] = { |
BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), |
BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) |
static const mbedtls_mpi_uint secp224k1_p[] = { |
BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
static const mbedtls_mpi_uint secp224k1_a[] = { |
BYTES_TO_T_UINT_2( 0x00, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp224k1_b[] = { |
BYTES_TO_T_UINT_2( 0x05, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp224k1_gx[] = { |
BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), |
BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), |
BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), |
BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), |
}; |
static const mbedtls_mpi_uint secp224k1_gy[] = { |
BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), |
BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), |
BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), |
BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), |
}; |
static const mbedtls_mpi_uint secp224k1_n[] = { |
BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), |
BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), |
BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), |
BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
static const mbedtls_mpi_uint secp256k1_p[] = { |
BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
static const mbedtls_mpi_uint secp256k1_a[] = { |
BYTES_TO_T_UINT_2( 0x00, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp256k1_b[] = { |
BYTES_TO_T_UINT_2( 0x07, 0x00 ), |
}; |
static const mbedtls_mpi_uint secp256k1_gx[] = { |
BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), |
BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), |
BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), |
BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), |
}; |
static const mbedtls_mpi_uint secp256k1_gy[] = { |
BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), |
BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), |
BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), |
BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), |
}; |
static const mbedtls_mpi_uint secp256k1_n[] = { |
BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), |
BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), |
BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), |
}; |
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ |
/* |
* Domain parameters for brainpoolP256r1 (RFC 5639 3.4) |
*/ |
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) |
static const mbedtls_mpi_uint brainpoolP256r1_p[] = { |
BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), |
BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), |
BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), |
BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), |
}; |
static const mbedtls_mpi_uint brainpoolP256r1_a[] = { |
BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), |
BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), |
BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), |
BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), |
}; |
static const mbedtls_mpi_uint brainpoolP256r1_b[] = { |
BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), |
BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), |
BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), |
BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), |
}; |
static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { |
BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), |
BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), |
BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), |
BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), |
}; |
static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { |
BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), |
BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), |
BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), |
BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), |
}; |
static const mbedtls_mpi_uint brainpoolP256r1_n[] = { |
BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), |
BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), |
BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), |
BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), |
}; |
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ |
/* |
* Domain parameters for brainpoolP384r1 (RFC 5639 3.6) |
*/ |
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) |
static const mbedtls_mpi_uint brainpoolP384r1_p[] = { |
BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), |
BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), |
BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), |
BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), |
BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), |
BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), |
}; |
static const mbedtls_mpi_uint brainpoolP384r1_a[] = { |
BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), |
BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), |
BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), |
BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), |
BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), |
BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), |
}; |
static const mbedtls_mpi_uint brainpoolP384r1_b[] = { |
BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), |
BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), |
BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), |
BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), |
BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), |
BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), |
}; |
static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { |
BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), |
BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), |
BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), |
BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), |
BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), |
BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), |
}; |
static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { |
BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), |
BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), |
BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), |
BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), |
BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), |
BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), |
}; |
static const mbedtls_mpi_uint brainpoolP384r1_n[] = { |
BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), |
BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), |
BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), |
BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), |
BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), |
BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), |
}; |
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ |
/* |
* Domain parameters for brainpoolP512r1 (RFC 5639 3.7) |
*/ |
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) |
static const mbedtls_mpi_uint brainpoolP512r1_p[] = { |
BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), |
BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), |
BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), |
BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), |
BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), |
BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), |
BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), |
BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), |
}; |
static const mbedtls_mpi_uint brainpoolP512r1_a[] = { |
BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), |
BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), |
BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), |
BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), |
BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), |
BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), |
BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), |
BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), |
}; |
static const mbedtls_mpi_uint brainpoolP512r1_b[] = { |
BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), |
BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), |
BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), |
BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), |
BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), |
BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), |
BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), |
BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), |
}; |
static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { |
BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), |
BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), |
BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), |
BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), |
BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), |
BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), |
BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), |
BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), |
}; |
static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { |
BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), |
BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), |
BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), |
BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), |
BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), |
BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), |
BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), |
BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), |
}; |
static const mbedtls_mpi_uint brainpoolP512r1_n[] = { |
BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), |
BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), |
BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), |
BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), |
BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), |
BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), |
BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), |
BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), |
}; |
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ |
/* |
* Create an MPI from embedded constants |
* (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) |
*/ |
static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) |
{ |
X->s = 1; |
X->n = len / sizeof( mbedtls_mpi_uint ); |
X->p = (mbedtls_mpi_uint *) p; |
} |
/* |
* Set an MPI to static value 1 |
*/ |
static inline void ecp_mpi_set1( mbedtls_mpi *X ) |
{ |
static mbedtls_mpi_uint one[] = { 1 }; |
X->s = 1; |
X->n = 1; |
X->p = one; |
} |
/* |
* Make group available from embedded constants |
*/ |
static int ecp_group_load( mbedtls_ecp_group *grp, |
const mbedtls_mpi_uint *p, size_t plen, |
const mbedtls_mpi_uint *a, size_t alen, |
const mbedtls_mpi_uint *b, size_t blen, |
const mbedtls_mpi_uint *gx, size_t gxlen, |
const mbedtls_mpi_uint *gy, size_t gylen, |
const mbedtls_mpi_uint *n, size_t nlen) |
{ |
ecp_mpi_load( &grp->P, p, plen ); |
if( a != NULL ) |
ecp_mpi_load( &grp->A, a, alen ); |
ecp_mpi_load( &grp->B, b, blen ); |
ecp_mpi_load( &grp->N, n, nlen ); |
ecp_mpi_load( &grp->G.X, gx, gxlen ); |
ecp_mpi_load( &grp->G.Y, gy, gylen ); |
ecp_mpi_set1( &grp->G.Z ); |
grp->pbits = mbedtls_mpi_bitlen( &grp->P ); |
grp->nbits = mbedtls_mpi_bitlen( &grp->N ); |
grp->h = 1; |
return( 0 ); |
} |
#if defined(MBEDTLS_ECP_NIST_OPTIM) |
/* Forward declarations */ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
static int ecp_mod_p192( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) |
static int ecp_mod_p224( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
static int ecp_mod_p256( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
static int ecp_mod_p384( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) |
static int ecp_mod_p521( mbedtls_mpi * ); |
#endif |
#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; |
#else |
#define NIST_MODP( P ) |
#endif /* MBEDTLS_ECP_NIST_OPTIM */ |
/* Additional forward declarations */ |
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) |
static int ecp_mod_p255( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) |
static int ecp_mod_p448( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) |
static int ecp_mod_p192k1( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) |
static int ecp_mod_p224k1( mbedtls_mpi * ); |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
static int ecp_mod_p256k1( mbedtls_mpi * ); |
#endif |
#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ |
G ## _p, sizeof( G ## _p ), \ |
G ## _a, sizeof( G ## _a ), \ |
G ## _b, sizeof( G ## _b ), \ |
G ## _gx, sizeof( G ## _gx ), \ |
G ## _gy, sizeof( G ## _gy ), \ |
G ## _n, sizeof( G ## _n ) ) |
#define LOAD_GROUP( G ) ecp_group_load( grp, \ |
G ## _p, sizeof( G ## _p ), \ |
NULL, 0, \ |
G ## _b, sizeof( G ## _b ), \ |
G ## _gx, sizeof( G ## _gx ), \ |
G ## _gy, sizeof( G ## _gy ), \ |
G ## _n, sizeof( G ## _n ) ) |
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) |
/* |
* Specialized function for creating the Curve25519 group |
*/ |
static int ecp_use_curve25519( mbedtls_ecp_group *grp ) |
{ |
int ret; |
/* Actually ( A + 2 ) / 4 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); |
/* P = 2^255 - 19 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); |
grp->pbits = mbedtls_mpi_bitlen( &grp->P ); |
/* N = 2^252 + 27742317777372353535851937790883648493 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16, |
"14DEF9DEA2F79CD65812631A5CF5D3ED" ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); |
/* Y intentionally not set, since we use x/z coordinates. |
* This is used as a marker to identify Montgomery curves! */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); |
mbedtls_mpi_free( &grp->G.Y ); |
/* Actually, the required msb for private keys */ |
grp->nbits = 254; |
cleanup: |
if( ret != 0 ) |
mbedtls_ecp_group_free( grp ); |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) |
/* |
* Specialized function for creating the Curve448 group |
*/ |
static int ecp_use_curve448( mbedtls_ecp_group *grp ) |
{ |
mbedtls_mpi Ns; |
int ret; |
mbedtls_mpi_init( &Ns ); |
/* Actually ( A + 2 ) / 4 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) ); |
/* P = 2^448 - 2^224 - 1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); |
grp->pbits = mbedtls_mpi_bitlen( &grp->P ); |
/* Y intentionally not set, since we use x/z coordinates. |
* This is used as a marker to identify Montgomery curves! */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); |
mbedtls_mpi_free( &grp->G.Y ); |
/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16, |
"8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); |
/* Actually, the required msb for private keys */ |
grp->nbits = 447; |
cleanup: |
mbedtls_mpi_free( &Ns ); |
if( ret != 0 ) |
mbedtls_ecp_group_free( grp ); |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ |
/* |
* Set a group using well-known domain parameters |
*/ |
int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) |
{ |
ECP_VALIDATE_RET( grp != NULL ); |
mbedtls_ecp_group_free( grp ); |
grp->id = id; |
switch( id ) |
{ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
case MBEDTLS_ECP_DP_SECP192R1: |
NIST_MODP( p192 ); |
return( LOAD_GROUP( secp192r1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) |
case MBEDTLS_ECP_DP_SECP224R1: |
NIST_MODP( p224 ); |
return( LOAD_GROUP( secp224r1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
case MBEDTLS_ECP_DP_SECP256R1: |
NIST_MODP( p256 ); |
return( LOAD_GROUP( secp256r1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
case MBEDTLS_ECP_DP_SECP384R1: |
NIST_MODP( p384 ); |
return( LOAD_GROUP( secp384r1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) |
case MBEDTLS_ECP_DP_SECP521R1: |
NIST_MODP( p521 ); |
return( LOAD_GROUP( secp521r1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) |
case MBEDTLS_ECP_DP_SECP192K1: |
grp->modp = ecp_mod_p192k1; |
return( LOAD_GROUP_A( secp192k1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) |
case MBEDTLS_ECP_DP_SECP224K1: |
grp->modp = ecp_mod_p224k1; |
return( LOAD_GROUP_A( secp224k1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
case MBEDTLS_ECP_DP_SECP256K1: |
grp->modp = ecp_mod_p256k1; |
return( LOAD_GROUP_A( secp256k1 ) ); |
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) |
case MBEDTLS_ECP_DP_BP256R1: |
return( LOAD_GROUP_A( brainpoolP256r1 ) ); |
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) |
case MBEDTLS_ECP_DP_BP384R1: |
return( LOAD_GROUP_A( brainpoolP384r1 ) ); |
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) |
case MBEDTLS_ECP_DP_BP512R1: |
return( LOAD_GROUP_A( brainpoolP512r1 ) ); |
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) |
case MBEDTLS_ECP_DP_CURVE25519: |
grp->modp = ecp_mod_p255; |
return( ecp_use_curve25519( grp ) ); |
#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) |
case MBEDTLS_ECP_DP_CURVE448: |
grp->modp = ecp_mod_p448; |
return( ecp_use_curve448( grp ) ); |
#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ |
default: |
mbedtls_ecp_group_free( grp ); |
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); |
} |
} |
#if defined(MBEDTLS_ECP_NIST_OPTIM) |
/* |
* Fast reduction modulo the primes used by the NIST curves. |
* |
* These functions are critical for speed, but not needed for correct |
* operations. So, we make the choice to heavily rely on the internals of our |
* bignum library, which creates a tight coupling between these functions and |
* our MPI implementation. However, the coupling between the ECP module and |
* MPI remains loose, since these functions can be deactivated at will. |
*/ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
/* |
* Compared to the way things are presented in FIPS 186-3 D.2, |
* we proceed in columns, from right (least significant chunk) to left, |
* adding chunks to N in place, and keeping a carry for the next chunk. |
* This avoids moving things around in memory, and uselessly adding zeros, |
* compared to the more straightforward, line-oriented approach. |
* |
* For this prime we need to handle data in chunks of 64 bits. |
* Since this is always a multiple of our basic mbedtls_mpi_uint, we can |
* use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. |
*/ |
/* Add 64-bit chunks (dst += src) and update carry */ |
static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) |
{ |
unsigned char i; |
mbedtls_mpi_uint c = 0; |
for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) |
{ |
*dst += c; c = ( *dst < c ); |
*dst += *src; c += ( *dst < *src ); |
} |
*carry += c; |
} |
/* Add carry to a 64-bit chunk and update carry */ |
static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) |
{ |
unsigned char i; |
for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) |
{ |
*dst += *carry; |
*carry = ( *dst < *carry ); |
} |
} |
#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) |
#define A( i ) N->p + (i) * WIDTH |
#define ADD( i ) add64( p, A( i ), &c ) |
#define NEXT p += WIDTH; carry64( p, &c ) |
#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 |
/* |
* Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) |
*/ |
static int ecp_mod_p192( mbedtls_mpi *N ) |
{ |
int ret; |
mbedtls_mpi_uint c = 0; |
mbedtls_mpi_uint *p, *end; |
/* Make sure we have enough blocks so that A(5) is legal */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); |
p = N->p; |
end = p + N->n; |
ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 |
ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 |
ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 |
cleanup: |
return( ret ); |
} |
#undef WIDTH |
#undef A |
#undef ADD |
#undef NEXT |
#undef LAST |
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
/* |
* The reader is advised to first understand ecp_mod_p192() since the same |
* general structure is used here, but with additional complications: |
* (1) chunks of 32 bits, and (2) subtractions. |
*/ |
/* |
* For these primes, we need to handle data in chunks of 32 bits. |
* This makes it more complicated if we use 64 bits limbs in MPI, |
* which prevents us from using a uniform access method as for p192. |
* |
* So, we define a mini abstraction layer to access 32 bit chunks, |
* load them in 'cur' for work, and store them back from 'cur' when done. |
* |
* While at it, also define the size of N in terms of 32-bit chunks. |
*/ |
#define LOAD32 cur = A( i ); |
#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ |
#define MAX32 N->n |
#define A( j ) N->p[j] |
#define STORE32 N->p[i] = cur; |
#else /* 64-bit */ |
#define MAX32 N->n * 2 |
#define A( j ) (j) % 2 ? (uint32_t)( N->p[(j)/2] >> 32 ) : \ |
(uint32_t)( N->p[(j)/2] ) |
#define STORE32 \ |
if( i % 2 ) { \ |
N->p[i/2] &= 0x00000000FFFFFFFF; \ |
N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ |
} else { \ |
N->p[i/2] &= 0xFFFFFFFF00000000; \ |
N->p[i/2] |= (mbedtls_mpi_uint) cur; \ |
} |
#endif /* sizeof( mbedtls_mpi_uint ) */ |
/* |
* Helpers for addition and subtraction of chunks, with signed carry. |
*/ |
static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) |
{ |
*dst += src; |
*carry += ( *dst < src ); |
} |
static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) |
{ |
*carry -= ( *dst < src ); |
*dst -= src; |
} |
#define ADD( j ) add32( &cur, A( j ), &c ); |
#define SUB( j ) sub32( &cur, A( j ), &c ); |
/* |
* Helpers for the main 'loop' |
* (see fix_negative for the motivation of C) |
*/ |
#define INIT( b ) \ |
int ret; \ |
signed char c = 0, cc; \ |
uint32_t cur; \ |
size_t i = 0, bits = (b); \ |
mbedtls_mpi C; \ |
mbedtls_mpi_uint Cp[ (b) / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ |
\ |
C.s = 1; \ |
C.n = (b) / 8 / sizeof( mbedtls_mpi_uint) + 1; \ |
C.p = Cp; \ |
memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ |
\ |
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, (b) * 2 / 8 / \ |
sizeof( mbedtls_mpi_uint ) ) ); \ |
LOAD32; |
#define NEXT \ |
STORE32; i++; LOAD32; \ |
cc = c; c = 0; \ |
if( cc < 0 ) \ |
sub32( &cur, -cc, &c ); \ |
else \ |
add32( &cur, cc, &c ); \ |
#define LAST \ |
STORE32; i++; \ |
cur = c > 0 ? c : 0; STORE32; \ |
cur = 0; while( ++i < MAX32 ) { STORE32; } \ |
if( c < 0 ) fix_negative( N, c, &C, bits ); |
/* |
* If the result is negative, we get it in the form |
* c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' |
*/ |
static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) |
{ |
int ret; |
/* C = - c * 2^(bits + 32) */ |
#if !defined(MBEDTLS_HAVE_INT64) |
((void) bits); |
#else |
if( bits == 224 ) |
C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; |
else |
#endif |
C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; |
/* N = - ( C - N ) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); |
N->s = -1; |
cleanup: |
return( ret ); |
} |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) |
/* |
* Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) |
*/ |
static int ecp_mod_p224( mbedtls_mpi *N ) |
{ |
INIT( 224 ); |
SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 |
SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 |
SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 |
SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 |
SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 |
SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 |
SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
/* |
* Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) |
*/ |
static int ecp_mod_p256( mbedtls_mpi *N ) |
{ |
INIT( 256 ); |
ADD( 8 ); ADD( 9 ); |
SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 |
ADD( 9 ); ADD( 10 ); |
SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 |
ADD( 10 ); ADD( 11 ); |
SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 |
ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); |
SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 |
ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); |
SUB( 9 ); SUB( 10 ); NEXT; // A4 |
ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); |
SUB( 10 ); SUB( 11 ); NEXT; // A5 |
ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); |
SUB( 8 ); SUB( 9 ); NEXT; // A6 |
ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); |
SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
/* |
* Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) |
*/ |
static int ecp_mod_p384( mbedtls_mpi *N ) |
{ |
INIT( 384 ); |
ADD( 12 ); ADD( 21 ); ADD( 20 ); |
SUB( 23 ); NEXT; // A0 |
ADD( 13 ); ADD( 22 ); ADD( 23 ); |
SUB( 12 ); SUB( 20 ); NEXT; // A2 |
ADD( 14 ); ADD( 23 ); |
SUB( 13 ); SUB( 21 ); NEXT; // A2 |
ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); |
SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 |
ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); |
SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 |
ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); |
SUB( 16 ); NEXT; // A5 |
ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); |
SUB( 17 ); NEXT; // A6 |
ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); |
SUB( 18 ); NEXT; // A7 |
ADD( 20 ); ADD( 17 ); ADD( 16 ); |
SUB( 19 ); NEXT; // A8 |
ADD( 21 ); ADD( 18 ); ADD( 17 ); |
SUB( 20 ); NEXT; // A9 |
ADD( 22 ); ADD( 19 ); ADD( 18 ); |
SUB( 21 ); NEXT; // A10 |
ADD( 23 ); ADD( 20 ); ADD( 19 ); |
SUB( 22 ); LAST; // A11 |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ |
#undef A |
#undef LOAD32 |
#undef STORE32 |
#undef MAX32 |
#undef INIT |
#undef NEXT |
#undef LAST |
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || |
MBEDTLS_ECP_DP_SECP256R1_ENABLED || |
MBEDTLS_ECP_DP_SECP384R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) |
/* |
* Here we have an actual Mersenne prime, so things are more straightforward. |
* However, chunks are aligned on a 'weird' boundary (521 bits). |
*/ |
/* Size of p521 in terms of mbedtls_mpi_uint */ |
#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) |
/* Bits to keep in the most significant mbedtls_mpi_uint */ |
#define P521_MASK 0x01FF |
/* |
* Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) |
* Write N as A1 + 2^521 A0, return A0 + A1 |
*/ |
static int ecp_mod_p521( mbedtls_mpi *N ) |
{ |
int ret; |
size_t i; |
mbedtls_mpi M; |
mbedtls_mpi_uint Mp[P521_WIDTH + 1]; |
/* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: |
* we need to hold bits 513 to 1056, which is 34 limbs, that is |
* P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ |
if( N->n < P521_WIDTH ) |
return( 0 ); |
/* M = A1 */ |
M.s = 1; |
M.n = N->n - ( P521_WIDTH - 1 ); |
if( M.n > P521_WIDTH + 1 ) |
M.n = P521_WIDTH + 1; |
M.p = Mp; |
memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); |
/* N = A0 */ |
N->p[P521_WIDTH - 1] &= P521_MASK; |
for( i = P521_WIDTH; i < N->n; i++ ) |
N->p[i] = 0; |
/* N = A0 + A1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); |
cleanup: |
return( ret ); |
} |
#undef P521_WIDTH |
#undef P521_MASK |
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ |
#endif /* MBEDTLS_ECP_NIST_OPTIM */ |
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) |
/* Size of p255 in terms of mbedtls_mpi_uint */ |
#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) |
/* |
* Fast quasi-reduction modulo p255 = 2^255 - 19 |
* Write N as A0 + 2^255 A1, return A0 + 19 * A1 |
*/ |
static int ecp_mod_p255( mbedtls_mpi *N ) |
{ |
int ret; |
size_t i; |
mbedtls_mpi M; |
mbedtls_mpi_uint Mp[P255_WIDTH + 2]; |
if( N->n < P255_WIDTH ) |
return( 0 ); |
/* M = A1 */ |
M.s = 1; |
M.n = N->n - ( P255_WIDTH - 1 ); |
if( M.n > P255_WIDTH + 1 ) |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
M.p = Mp; |
memset( Mp, 0, sizeof Mp ); |
memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); |
M.n++; /* Make room for multiplication by 19 */ |
/* N = A0 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); |
for( i = P255_WIDTH; i < N->n; i++ ) |
N->p[i] = 0; |
/* N = A0 + 19 * A1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) |
/* Size of p448 in terms of mbedtls_mpi_uint */ |
#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) |
/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ |
#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) |
#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) |
#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) |
#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) |
/* |
* Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 |
* Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return |
* A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference |
* implementation of Curve448, which uses its own special 56-bit limbs rather |
* than a generic bignum library. We could squeeze some extra speed out on |
* 32-bit machines by splitting N up into 32-bit limbs and doing the |
* arithmetic using the limbs directly as we do for the NIST primes above, |
* but for 64-bit targets it should use half the number of operations if we do |
* the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. |
*/ |
static int ecp_mod_p448( mbedtls_mpi *N ) |
{ |
int ret; |
size_t i; |
mbedtls_mpi M, Q; |
mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; |
if( N->n <= P448_WIDTH ) |
return( 0 ); |
/* M = A1 */ |
M.s = 1; |
M.n = N->n - ( P448_WIDTH ); |
if( M.n > P448_WIDTH ) |
/* Shouldn't be called with N larger than 2^896! */ |
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
M.p = Mp; |
memset( Mp, 0, sizeof( Mp ) ); |
memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); |
/* N = A0 */ |
for( i = P448_WIDTH; i < N->n; i++ ) |
N->p[i] = 0; |
/* N += A1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); |
/* Q = B1, N += B1 */ |
Q = M; |
Q.p = Qp; |
memcpy( Qp, Mp, sizeof( Qp ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); |
/* M = (B0 + B1) * 2^224, N += M */ |
if( sizeof( mbedtls_mpi_uint ) > 4 ) |
Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); |
for( i = P224_WIDTH_MAX; i < M.n; ++i ) |
Mp[i] = 0; |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); |
M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ |
defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
/* |
* Fast quasi-reduction modulo P = 2^s - R, |
* with R about 33 bits, used by the Koblitz curves. |
* |
* Write N as A0 + 2^224 A1, return A0 + R * A1. |
* Actually do two passes, since R is big. |
*/ |
#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P |
#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R |
static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, |
size_t adjust, size_t shift, mbedtls_mpi_uint mask ) |
{ |
int ret; |
size_t i; |
mbedtls_mpi M, R; |
mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; |
if( N->n < p_limbs ) |
return( 0 ); |
/* Init R */ |
R.s = 1; |
R.p = Rp; |
R.n = P_KOBLITZ_R; |
/* Common setup for M */ |
M.s = 1; |
M.p = Mp; |
/* M = A1 */ |
M.n = N->n - ( p_limbs - adjust ); |
if( M.n > p_limbs + adjust ) |
M.n = p_limbs + adjust; |
memset( Mp, 0, sizeof Mp ); |
memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); |
if( shift != 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); |
M.n += R.n; /* Make room for multiplication by R */ |
/* N = A0 */ |
if( mask != 0 ) |
N->p[p_limbs - 1] &= mask; |
for( i = p_limbs; i < N->n; i++ ) |
N->p[i] = 0; |
/* N = A0 + R * A1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); |
/* Second pass */ |
/* M = A1 */ |
M.n = N->n - ( p_limbs - adjust ); |
if( M.n > p_limbs + adjust ) |
M.n = p_limbs + adjust; |
memset( Mp, 0, sizeof Mp ); |
memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); |
if( shift != 0 ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); |
M.n += R.n; /* Make room for multiplication by R */ |
/* N = A0 */ |
if( mask != 0 ) |
N->p[p_limbs - 1] &= mask; |
for( i = p_limbs; i < N->n; i++ ) |
N->p[i] = 0; |
/* N = A0 + R * A1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || |
MBEDTLS_ECP_DP_SECP224K1_ENABLED) || |
MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) |
/* |
* Fast quasi-reduction modulo p192k1 = 2^192 - R, |
* with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 |
*/ |
static int ecp_mod_p192k1( mbedtls_mpi *N ) |
{ |
static mbedtls_mpi_uint Rp[] = { |
BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; |
return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); |
} |
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) |
/* |
* Fast quasi-reduction modulo p224k1 = 2^224 - R, |
* with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 |
*/ |
static int ecp_mod_p224k1( mbedtls_mpi *N ) |
{ |
static mbedtls_mpi_uint Rp[] = { |
BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; |
#if defined(MBEDTLS_HAVE_INT64) |
return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); |
#else |
return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); |
#endif |
} |
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
/* |
* Fast quasi-reduction modulo p256k1 = 2^256 - R, |
* with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 |
*/ |
static int ecp_mod_p256k1( mbedtls_mpi *N ) |
{ |
static mbedtls_mpi_uint Rp[] = { |
BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; |
return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); |
} |
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ |
#endif /* !MBEDTLS_ECP_ALT */ |
#endif /* MBEDTLS_ECP_C */ |
/programs/develop/libraries/kos_mbedtls/library/entropy.c |
---|
0,0 → 1,749 |
/* |
* Entropy accumulator implementation |
* |
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ENTROPY_C) |
#if defined(MBEDTLS_TEST_NULL_ENTROPY) |
#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " |
#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " |
#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " |
#endif |
#include "mbedtls/entropy.h" |
#include "mbedtls/entropy_poll.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_FS_IO) |
#include <stdio.h> |
#endif |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
#include "mbedtls/platform.h" |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if defined(MBEDTLS_HAVEGE_C) |
#include "mbedtls/havege.h" |
#endif |
#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ |
void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) |
{ |
ctx->source_count = 0; |
memset( ctx->source, 0, sizeof( ctx->source ) ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &ctx->mutex ); |
#endif |
ctx->accumulator_started = 0; |
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) |
mbedtls_sha512_init( &ctx->accumulator ); |
#else |
mbedtls_sha256_init( &ctx->accumulator ); |
#endif |
#if defined(MBEDTLS_HAVEGE_C) |
mbedtls_havege_init( &ctx->havege_data ); |
#endif |
/* Reminder: Update ENTROPY_HAVE_STRONG in the test files |
* when adding more strong entropy sources here. */ |
/* add KolibriOS entropy sources */ |
mbedtls_entropy_add_source( ctx, mbedtls_sysfn_3_poll, NULL, |
4, MBEDTLS_ENTROPY_SOURCE_WEAK ); |
mbedtls_entropy_add_source( ctx, mbedtls_sysfn_26_9_poll, NULL, |
4, MBEDTLS_ENTROPY_SOURCE_WEAK ); |
mbedtls_entropy_add_source( ctx, mbedtls_sysfn_14_poll, NULL, |
4, MBEDTLS_ENTROPY_SOURCE_WEAK ); |
mbedtls_entropy_add_source( ctx, mbedtls_sysfn_18_4_poll, NULL, |
4, MBEDTLS_ENTROPY_SOURCE_STRONG ); |
mbedtls_entropy_add_source( ctx, mbedtls_sysfn_37_0_poll, NULL, |
4, MBEDTLS_ENTROPY_SOURCE_WEAK ); |
mbedtls_entropy_add_source( ctx, mbedtls_sysfn_66_3_poll, NULL, |
4, MBEDTLS_ENTROPY_SOURCE_WEAK ); |
mbedtls_entropy_add_source( ctx, mbedtls_sysfn_68_0_poll, NULL, |
4, MBEDTLS_ENTROPY_SOURCE_STRONG ); |
#if defined(MBEDTLS_TEST_NULL_ENTROPY) |
mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, |
1, MBEDTLS_ENTROPY_SOURCE_STRONG ); |
#endif |
#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) |
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) |
mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, |
MBEDTLS_ENTROPY_MIN_PLATFORM, |
MBEDTLS_ENTROPY_SOURCE_STRONG ); |
#endif |
#if defined(MBEDTLS_TIMING_C) |
mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, |
MBEDTLS_ENTROPY_MIN_HARDCLOCK, |
MBEDTLS_ENTROPY_SOURCE_WEAK ); |
#endif |
#if defined(MBEDTLS_HAVEGE_C) |
mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, |
MBEDTLS_ENTROPY_MIN_HAVEGE, |
MBEDTLS_ENTROPY_SOURCE_STRONG ); |
#endif |
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) |
mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, |
MBEDTLS_ENTROPY_MIN_HARDWARE, |
MBEDTLS_ENTROPY_SOURCE_STRONG ); |
#endif |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, |
MBEDTLS_ENTROPY_BLOCK_SIZE, |
MBEDTLS_ENTROPY_SOURCE_STRONG ); |
ctx->initial_entropy_run = 0; |
#endif |
#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ |
} |
void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) |
{ |
#if defined(MBEDTLS_HAVEGE_C) |
mbedtls_havege_free( &ctx->havege_data ); |
#endif |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &ctx->mutex ); |
#endif |
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) |
mbedtls_sha512_free( &ctx->accumulator ); |
#else |
mbedtls_sha256_free( &ctx->accumulator ); |
#endif |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
ctx->initial_entropy_run = 0; |
#endif |
ctx->source_count = 0; |
mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); |
ctx->accumulator_started = 0; |
} |
int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, |
mbedtls_entropy_f_source_ptr f_source, void *p_source, |
size_t threshold, int strong ) |
{ |
int idx, ret = 0; |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
idx = ctx->source_count; |
if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) |
{ |
ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; |
goto exit; |
} |
ctx->source[idx].f_source = f_source; |
ctx->source[idx].p_source = p_source; |
ctx->source[idx].threshold = threshold; |
ctx->source[idx].strong = strong; |
ctx->source_count++; |
exit: |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
/* |
* Entropy accumulator update |
*/ |
static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, |
const unsigned char *data, size_t len ) |
{ |
unsigned char header[2]; |
unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; |
size_t use_len = len; |
const unsigned char *p = data; |
int ret = 0; |
if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) |
{ |
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) |
if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) |
goto cleanup; |
#else |
if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) |
goto cleanup; |
#endif |
p = tmp; |
use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; |
} |
header[0] = source_id; |
header[1] = use_len & 0xFF; |
/* |
* Start the accumulator if this has not already happened. Note that |
* it is sufficient to start the accumulator here only because all calls to |
* gather entropy eventually execute this code. |
*/ |
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) |
if( ctx->accumulator_started == 0 && |
( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) |
goto cleanup; |
else |
ctx->accumulator_started = 1; |
if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) |
goto cleanup; |
ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); |
#else |
if( ctx->accumulator_started == 0 && |
( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) |
goto cleanup; |
else |
ctx->accumulator_started = 1; |
if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) |
goto cleanup; |
ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); |
#endif |
cleanup: |
mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); |
return( ret ); |
} |
int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, |
const unsigned char *data, size_t len ) |
{ |
int ret; |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
/* |
* Run through the different sources to add entropy to our accumulator |
*/ |
static int entropy_gather_internal( mbedtls_entropy_context *ctx ) |
{ |
int ret, i, have_one_strong = 0; |
unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; |
size_t olen; |
if( ctx->source_count == 0 ) |
return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); |
/* |
* Run through our entropy sources |
*/ |
for( i = 0; i < ctx->source_count; i++ ) |
{ |
if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) |
have_one_strong = 1; |
olen = 0; |
if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, |
buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) |
{ |
goto cleanup; |
} |
/* |
* Add if we actually gathered something |
*/ |
if( olen > 0 ) |
{ |
if( ( ret = entropy_update( ctx, (unsigned char) i, |
buf, olen ) ) != 0 ) |
return( ret ); |
ctx->source[i].size += olen; |
} |
} |
if( have_one_strong == 0 ) |
ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; |
cleanup: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
return( ret ); |
} |
/* |
* Thread-safe wrapper for entropy_gather_internal() |
*/ |
int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) |
{ |
int ret; |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
ret = entropy_gather_internal( ctx ); |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) |
{ |
int ret, count = 0, i, done; |
mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; |
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; |
if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
/* Update the NV entropy seed before generating any entropy for outside |
* use. |
*/ |
if( ctx->initial_entropy_run == 0 ) |
{ |
ctx->initial_entropy_run = 1; |
if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) |
return( ret ); |
} |
#endif |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
/* |
* Always gather extra entropy before a call |
*/ |
do |
{ |
if( count++ > ENTROPY_MAX_LOOP ) |
{ |
/*for( i = 0; i < ctx->source_count; i++ ) { // rgimad |
mbedtls_printf("ctx->source[%d].size = %d\n", i, ctx->source[i].size); |
}*/ |
ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; |
goto exit; |
} |
if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) |
goto exit; |
done = 1; |
for( i = 0; i < ctx->source_count; i++ ) |
if( ctx->source[i].size < ctx->source[i].threshold ) |
done = 0; |
} |
while( ! done ); |
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); |
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) |
/* |
* Note that at this stage it is assumed that the accumulator was started |
* in a previous call to entropy_update(). If this is not guaranteed, the |
* code below will fail. |
*/ |
if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) |
goto exit; |
/* |
* Reset accumulator and counters and recycle existing entropy |
*/ |
mbedtls_sha512_free( &ctx->accumulator ); |
mbedtls_sha512_init( &ctx->accumulator ); |
if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, |
MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) |
goto exit; |
/* |
* Perform second SHA-512 on entropy |
*/ |
if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, |
buf, 0 ) ) != 0 ) |
goto exit; |
#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ |
if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) |
goto exit; |
/* |
* Reset accumulator and counters and recycle existing entropy |
*/ |
mbedtls_sha256_free( &ctx->accumulator ); |
mbedtls_sha256_init( &ctx->accumulator ); |
if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, |
MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) |
goto exit; |
/* |
* Perform second SHA-256 on entropy |
*/ |
if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, |
buf, 0 ) ) != 0 ) |
goto exit; |
#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ |
for( i = 0; i < ctx->source_count; i++ ) |
ctx->source[i].size = 0; |
memcpy( output, buf, len ); |
ret = 0; |
exit: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) |
{ |
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; |
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; |
/* Read new seed and write it to NV */ |
if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) |
return( ret ); |
if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) |
return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); |
/* Manually update the remaining stream with a separator value to diverge */ |
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); |
ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); |
return( ret ); |
} |
#endif /* MBEDTLS_ENTROPY_NV_SEED */ |
#if defined(MBEDTLS_FS_IO) |
int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) |
{ |
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; |
FILE *f; |
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; |
if( ( f = fopen( path, "wb" ) ) == NULL ) |
return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); |
if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) |
goto exit; |
if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) |
{ |
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; |
goto exit; |
} |
ret = 0; |
exit: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
fclose( f ); |
return( ret ); |
} |
int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) |
{ |
int ret = 0; |
FILE *f; |
size_t n; |
unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; |
if( ( f = fopen( path, "rb" ) ) == NULL ) |
return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); |
fseek( f, 0, SEEK_END ); |
n = (size_t) ftell( f ); |
fseek( f, 0, SEEK_SET ); |
if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) |
n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; |
if( fread( buf, 1, n, f ) != n ) |
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; |
else |
ret = mbedtls_entropy_update_manual( ctx, buf, n ); |
fclose( f ); |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
if( ret != 0 ) |
return( ret ); |
return( mbedtls_entropy_write_seed_file( ctx, path ) ); |
} |
#endif /* MBEDTLS_FS_IO */ |
#if defined(MBEDTLS_SELF_TEST) |
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) |
/* |
* Dummy source function |
*/ |
static int entropy_dummy_source( void *data, unsigned char *output, |
size_t len, size_t *olen ) |
{ |
((void) data); |
memset( output, 0x2a, len ); |
*olen = len; |
return( 0 ); |
} |
#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ |
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) |
static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) |
{ |
int ret = 0; |
size_t entropy_len = 0; |
size_t olen = 0; |
size_t attempts = buf_len; |
while( attempts > 0 && entropy_len < buf_len ) |
{ |
if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, |
buf_len - entropy_len, &olen ) ) != 0 ) |
return( ret ); |
entropy_len += olen; |
attempts--; |
} |
if( entropy_len < buf_len ) |
{ |
ret = 1; |
} |
return( ret ); |
} |
static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, |
size_t buf_len ) |
{ |
unsigned char set= 0xFF; |
unsigned char unset = 0x00; |
size_t i; |
for( i = 0; i < buf_len; i++ ) |
{ |
set &= buf[i]; |
unset |= buf[i]; |
} |
return( set == 0xFF || unset == 0x00 ); |
} |
/* |
* A test to ensure hat the entropy sources are functioning correctly |
* and there is no obvious failure. The test performs the following checks: |
* - The entropy source is not providing only 0s (all bits unset) or 1s (all |
* bits set). |
* - The entropy source is not providing values in a pattern. Because the |
* hardware could be providing data in an arbitrary length, this check polls |
* the hardware entropy source twice and compares the result to ensure they |
* are not equal. |
* - The error code returned by the entropy source is not an error. |
*/ |
int mbedtls_entropy_source_self_test( int verbose ) |
{ |
int ret = 0; |
unsigned char buf0[2 * sizeof( unsigned long long int )]; |
unsigned char buf1[2 * sizeof( unsigned long long int )]; |
if( verbose != 0 ) |
mbedtls_printf( " ENTROPY_BIAS test: " ); |
memset( buf0, 0x00, sizeof( buf0 ) ); |
memset( buf1, 0x00, sizeof( buf1 ) ); |
if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) |
goto cleanup; |
if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) |
goto cleanup; |
/* Make sure that the returned values are not all 0 or 1 */ |
if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) |
goto cleanup; |
if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) |
goto cleanup; |
/* Make sure that the entropy source is not returning values in a |
* pattern */ |
ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; |
cleanup: |
if( verbose != 0 ) |
{ |
if( ret != 0 ) |
mbedtls_printf( "failed\n" ); |
else |
mbedtls_printf( "passed\n" ); |
mbedtls_printf( "\n" ); |
} |
return( ret != 0 ); |
} |
#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ |
/* |
* The actual entropy quality is hard to test, but we can at least |
* test that the functions don't cause errors and write the correct |
* amount of data to buffers. |
*/ |
int mbedtls_entropy_self_test( int verbose ) |
{ |
int ret = 1; |
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) |
mbedtls_entropy_context ctx; |
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; |
unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; |
size_t i, j; |
#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ |
if( verbose != 0 ) |
mbedtls_printf( " ENTROPY test: " ); |
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) |
mbedtls_entropy_init( &ctx ); |
/* First do a gather to make sure we have default sources */ |
if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) |
goto cleanup; |
ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, |
MBEDTLS_ENTROPY_SOURCE_WEAK ); |
if( ret != 0 ) |
goto cleanup; |
if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) |
goto cleanup; |
/* |
* To test that mbedtls_entropy_func writes correct number of bytes: |
* - use the whole buffer and rely on ASan to detect overruns |
* - collect entropy 8 times and OR the result in an accumulator: |
* any byte should then be 0 with probably 2^(-64), so requiring |
* each of the 32 or 64 bytes to be non-zero has a false failure rate |
* of at most 2^(-58) which is acceptable. |
*/ |
for( i = 0; i < 8; i++ ) |
{ |
if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) |
goto cleanup; |
for( j = 0; j < sizeof( buf ); j++ ) |
acc[j] |= buf[j]; |
} |
for( j = 0; j < sizeof( buf ); j++ ) |
{ |
if( acc[j] == 0 ) |
{ |
ret = 1; |
goto cleanup; |
} |
} |
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) |
if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) |
goto cleanup; |
#endif |
cleanup: |
mbedtls_entropy_free( &ctx ); |
#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ |
if( verbose != 0 ) |
{ |
if( ret != 0 ) |
mbedtls_printf( "failed\n" ); |
else |
mbedtls_printf( "passed\n" ); |
mbedtls_printf( "\n" ); |
} |
return( ret != 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_ENTROPY_C */ |
/programs/develop/libraries/kos_mbedtls/library/entropy_poll.c |
---|
0,0 → 1,379 |
/* |
* Platform-specific and custom entropy polling functions |
* |
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if defined(__linux__) |
/* Ensure that syscall() is available even when compiling with -std=c99 */ |
#define _GNU_SOURCE |
#endif |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#include <string.h> |
/*rgimad*/ |
#include <stdio.h> |
#if defined(MBEDTLS_ENTROPY_C) |
#include "mbedtls/entropy.h" |
#include "mbedtls/entropy_poll.h" |
#if defined(MBEDTLS_TIMING_C) |
#include "mbedtls/timing.h" |
#endif |
#if defined(MBEDTLS_HAVEGE_C) |
#include "mbedtls/havege.h" |
#endif |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
#include "mbedtls/platform.h" |
#endif |
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) |
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ |
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ |
!defined(__HAIKU__) |
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" |
#endif |
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) |
#if !defined(_WIN32_WINNT) |
#define _WIN32_WINNT 0x0400 |
#endif |
#include <windows.h> |
#include <wincrypt.h> |
int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, |
size_t *olen ) |
{ |
HCRYPTPROV provider; |
((void) data); |
*olen = 0; |
if( CryptAcquireContext( &provider, NULL, NULL, |
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) |
{ |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
} |
if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) |
{ |
CryptReleaseContext( provider, 0 ); |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
} |
CryptReleaseContext( provider, 0 ); |
*olen = len; |
return( 0 ); |
} |
#else /* _WIN32 && !EFIX64 && !EFI32 */ |
/* |
* Test for Linux getrandom() support. |
* Since there is no wrapper in the libc yet, use the generic syscall wrapper |
* available in GNU libc and compatible libc's (eg uClibc). |
*/ |
#if defined(__linux__) && defined(__GLIBC__) |
#include <unistd.h> |
#include <sys/syscall.h> |
#if defined(SYS_getrandom) |
#define HAVE_GETRANDOM |
#include <errno.h> |
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) |
{ |
/* MemSan cannot understand that the syscall writes to the buffer */ |
#if defined(__has_feature) |
#if __has_feature(memory_sanitizer) |
memset( buf, 0, buflen ); |
#endif |
#endif |
return( syscall( SYS_getrandom, buf, buflen, flags ) ); |
} |
#endif /* SYS_getrandom */ |
#endif /* __linux__ */ |
#include <stdio.h> |
int mbedtls_platform_entropy_poll( void *data, |
unsigned char *output, size_t len, size_t *olen ) |
{ |
FILE *file; |
size_t read_len; |
int ret; |
((void) data); |
#if defined(HAVE_GETRANDOM) |
ret = getrandom_wrapper( output, len, 0 ); |
if( ret >= 0 ) |
{ |
*olen = ret; |
return( 0 ); |
} |
else if( errno != ENOSYS ) |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
/* Fall through if the system call isn't known. */ |
#else |
((void) ret); |
#endif /* HAVE_GETRANDOM */ |
*olen = 0; |
file = fopen( "/dev/urandom", "rb" ); |
if( file == NULL ) |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
read_len = fread( output, 1, len, file ); |
if( read_len != len ) |
{ |
fclose( file ); |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
} |
fclose( file ); |
*olen = len; |
return( 0 ); |
} |
#endif /* _WIN32 && !EFIX64 && !EFI32 */ |
#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ |
/* -------------------------------------------------------------------------- */ |
/* entropy sources polls for KolibriOS */ |
int mbedtls_sysfn_3_poll( void *data, unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long kos_time, bcd_sec, bcd_min, bcd_hr, secs, mins, hrs, seconds; |
((void) data); |
asm volatile("int $0x40" : "=a"(kos_time) : "a"(3)); |
bcd_sec = (kos_time >> 16); |
bcd_min = ((kos_time & 0xFF00) >> 8); |
bcd_hr = (kos_time & 0xFF); |
secs = ((bcd_sec & 0xF0)>>4)*10 + (bcd_sec & 0x0F); |
mins = ((bcd_min & 0xF0)>>4)*10 + (bcd_min & 0x0F); |
hrs = ((bcd_hr & 0xF0)>>4)*10 + (bcd_hr & 0x0F); |
seconds = hrs*3600 + mins*60 + secs; |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &seconds, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
int mbedtls_sysfn_26_9_poll( void *data, unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long res; |
((void) data); |
asm volatile("int $0x40" : "=a"(res) : "a"(26), "b"(9)); |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &res, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
int mbedtls_sysfn_14_poll( void *data, unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long res; |
((void) data); |
asm volatile("int $0x40" : "=a"(res) : "a"(14)); |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &res, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
int mbedtls_sysfn_18_4_poll( void *data, unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long res; |
((void) data); |
asm volatile("int $0x40" : "=a"(res) : "a"(18), "b"(4)); |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &res, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
int mbedtls_sysfn_37_0_poll( void *data, unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long res; |
((void) data); |
asm volatile("int $0x40" : "=a"(res) : "a"(37), "b"(0)); |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &res, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
int mbedtls_sysfn_66_3_poll( void *data, unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long res; |
((void) data); |
asm volatile("int $0x40" : "=a"(res) : "a"(66), "b"(3)); |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &res, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
int mbedtls_sysfn_68_0_poll( void *data, unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long res; |
((void) data); |
asm volatile("int $0x40" : "=a"(res) : "a"(68), "b"(0)); |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &res, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
/* -------------------------------------------------------------------------- */ |
#if defined(MBEDTLS_TEST_NULL_ENTROPY) |
int mbedtls_null_entropy_poll( void *data, |
unsigned char *output, size_t len, size_t *olen ) |
{ |
((void) data); |
((void) output); |
*olen = 0; |
if( len < sizeof(unsigned char) ) |
return( 0 ); |
*olen = sizeof(unsigned char); |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_TIMING_C) |
int mbedtls_hardclock_poll( void *data, |
unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned long timer = mbedtls_timing_hardclock(); |
((void) data); |
*olen = 0; |
if( len < sizeof(unsigned long) ) |
return( 0 ); |
memcpy( output, &timer, sizeof(unsigned long) ); |
*olen = sizeof(unsigned long); |
return( 0 ); |
} |
#endif /* MBEDTLS_TIMING_C */ |
#if defined(MBEDTLS_HAVEGE_C) |
int mbedtls_havege_poll( void *data, |
unsigned char *output, size_t len, size_t *olen ) |
{ |
mbedtls_havege_state *hs = (mbedtls_havege_state *) data; |
*olen = 0; |
if( mbedtls_havege_random( hs, output, len ) != 0 ) |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
*olen = len; |
return( 0 ); |
} |
#endif /* MBEDTLS_HAVEGE_C */ |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
int mbedtls_nv_seed_poll( void *data, |
unsigned char *output, size_t len, size_t *olen ) |
{ |
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; |
size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; |
((void) data); |
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); |
if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) |
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); |
if( len < use_len ) |
use_len = len; |
memcpy( output, buf, use_len ); |
*olen = use_len; |
return( 0 ); |
} |
#endif /* MBEDTLS_ENTROPY_NV_SEED */ |
#endif /* MBEDTLS_ENTROPY_C */ |
/programs/develop/libraries/kos_mbedtls/library/error.c |
---|
0,0 → 1,918 |
/* |
* Error message information |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) |
#include "mbedtls/error.h" |
#include <string.h> |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#define mbedtls_snprintf snprintf |
#define mbedtls_time_t time_t |
#endif |
#if defined(MBEDTLS_ERROR_C) |
#include <stdio.h> |
#if defined(MBEDTLS_AES_C) |
#include "mbedtls/aes.h" |
#endif |
#if defined(MBEDTLS_ARC4_C) |
#include "mbedtls/arc4.h" |
#endif |
#if defined(MBEDTLS_ARIA_C) |
#include "mbedtls/aria.h" |
#endif |
#if defined(MBEDTLS_BASE64_C) |
#include "mbedtls/base64.h" |
#endif |
#if defined(MBEDTLS_BIGNUM_C) |
#include "mbedtls/bignum.h" |
#endif |
#if defined(MBEDTLS_BLOWFISH_C) |
#include "mbedtls/blowfish.h" |
#endif |
#if defined(MBEDTLS_CAMELLIA_C) |
#include "mbedtls/camellia.h" |
#endif |
#if defined(MBEDTLS_CCM_C) |
#include "mbedtls/ccm.h" |
#endif |
#if defined(MBEDTLS_CHACHA20_C) |
#include "mbedtls/chacha20.h" |
#endif |
#if defined(MBEDTLS_CHACHAPOLY_C) |
#include "mbedtls/chachapoly.h" |
#endif |
#if defined(MBEDTLS_CIPHER_C) |
#include "mbedtls/cipher.h" |
#endif |
#if defined(MBEDTLS_CMAC_C) |
#include "mbedtls/cmac.h" |
#endif |
#if defined(MBEDTLS_CTR_DRBG_C) |
#include "mbedtls/ctr_drbg.h" |
#endif |
#if defined(MBEDTLS_DES_C) |
#include "mbedtls/des.h" |
#endif |
#if defined(MBEDTLS_DHM_C) |
#include "mbedtls/dhm.h" |
#endif |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/ecp.h" |
#endif |
#if defined(MBEDTLS_ENTROPY_C) |
#include "mbedtls/entropy.h" |
#endif |
#if defined(MBEDTLS_GCM_C) |
#include "mbedtls/gcm.h" |
#endif |
#if defined(MBEDTLS_HKDF_C) |
#include "mbedtls/hkdf.h" |
#endif |
#if defined(MBEDTLS_HMAC_DRBG_C) |
#include "mbedtls/hmac_drbg.h" |
#endif |
#if defined(MBEDTLS_MD_C) |
#include "mbedtls/md.h" |
#endif |
#if defined(MBEDTLS_MD2_C) |
#include "mbedtls/md2.h" |
#endif |
#if defined(MBEDTLS_MD4_C) |
#include "mbedtls/md4.h" |
#endif |
#if defined(MBEDTLS_MD5_C) |
#include "mbedtls/md5.h" |
#endif |
#if defined(MBEDTLS_NET_C) |
#include "mbedtls/net_sockets.h" |
#endif |
#if defined(MBEDTLS_OID_C) |
#include "mbedtls/oid.h" |
#endif |
#if defined(MBEDTLS_PADLOCK_C) |
#include "mbedtls/padlock.h" |
#endif |
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_PK_C) |
#include "mbedtls/pk.h" |
#endif |
#if defined(MBEDTLS_PKCS12_C) |
#include "mbedtls/pkcs12.h" |
#endif |
#if defined(MBEDTLS_PKCS5_C) |
#include "mbedtls/pkcs5.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#endif |
#if defined(MBEDTLS_POLY1305_C) |
#include "mbedtls/poly1305.h" |
#endif |
#if defined(MBEDTLS_RIPEMD160_C) |
#include "mbedtls/ripemd160.h" |
#endif |
#if defined(MBEDTLS_RSA_C) |
#include "mbedtls/rsa.h" |
#endif |
#if defined(MBEDTLS_SHA1_C) |
#include "mbedtls/sha1.h" |
#endif |
#if defined(MBEDTLS_SHA256_C) |
#include "mbedtls/sha256.h" |
#endif |
#if defined(MBEDTLS_SHA512_C) |
#include "mbedtls/sha512.h" |
#endif |
#if defined(MBEDTLS_SSL_TLS_C) |
#include "mbedtls/ssl.h" |
#endif |
#if defined(MBEDTLS_THREADING_C) |
#include "mbedtls/threading.h" |
#endif |
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) |
#include "mbedtls/x509.h" |
#endif |
#if defined(MBEDTLS_XTEA_C) |
#include "mbedtls/xtea.h" |
#endif |
void mbedtls_strerror( int ret, char *buf, size_t buflen ) |
{ |
size_t len; |
int use_ret; |
if( buflen == 0 ) |
return; |
memset( buf, 0x00, buflen ); |
if( ret < 0 ) |
ret = -ret; |
if( ret & 0xFF80 ) |
{ |
use_ret = ret & 0xFF80; |
// High level error codes |
// |
// BEGIN generated code |
#if defined(MBEDTLS_CIPHER_C) |
if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); |
if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters" ); |
if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); |
if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); |
if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); |
if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); |
if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid. For example, because it was freed" ); |
if( use_ret == -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CIPHER - Cipher hardware accelerator failed" ); |
#endif /* MBEDTLS_CIPHER_C */ |
#if defined(MBEDTLS_DHM_C) |
if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) |
mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "DHM - Read or write of file failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - DHM hardware accelerator failed" ); |
if( use_ret == -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DHM - Setting the modulus and generator failed" ); |
#endif /* MBEDTLS_DHM_C */ |
#if defined(MBEDTLS_ECP_C) |
if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "ECP - The requested feature is not available, for example, the requested curve is not supported" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as ephemeral key, failed" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) |
mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); |
if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) ) |
mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" ); |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_MD_C) |
if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); |
if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); |
if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); |
if( use_ret == -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "MD - MD hardware accelerator failed" ); |
#endif /* MBEDTLS_MD_C */ |
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) |
if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) |
mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) |
mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) |
mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) |
mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) |
mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); |
if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); |
#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ |
#if defined(MBEDTLS_PK_C) |
if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); |
if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); |
if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); |
if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) |
mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); |
if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) |
mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); |
if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) |
mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); |
if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) |
mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); |
if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); |
if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) |
mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); |
if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) |
mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); |
if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) |
mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); |
if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); |
if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "PK - The buffer contains a valid signature followed by more data" ); |
if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" ); |
#endif /* MBEDTLS_PK_C */ |
#if defined(MBEDTLS_PKCS12_C) |
if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); |
if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) |
mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); |
if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); |
#endif /* MBEDTLS_PKCS12_C */ |
#if defined(MBEDTLS_PKCS5_C) |
if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) |
mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); |
if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); |
if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); |
#endif /* MBEDTLS_PKCS5_C */ |
#if defined(MBEDTLS_RSA_C) |
if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) |
mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the validity check of the library" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) |
mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) ) |
mbedtls_snprintf( buf, buflen, "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); |
if( use_ret == -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RSA - RSA hardware accelerator failed" ); |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_SSL_TLS_C) |
if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) |
mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) |
mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) |
mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) |
mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) |
mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) |
mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) |
mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) |
mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) |
mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) |
mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) |
mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) |
mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) |
{ |
mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); |
return; |
} |
if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) |
mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) |
mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) |
mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) |
mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) |
mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) |
mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) |
mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) |
mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) |
mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) |
mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) |
mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) |
mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) |
mbedtls_snprintf( buf, buflen, "SSL - No data of requested type currently available on underlying transport" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) |
mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) |
mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) |
mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) |
mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) |
mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) |
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) ) |
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) |
mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) ) |
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); |
if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) ) |
mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" ); |
#endif /* MBEDTLS_SSL_TLS_C */ |
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) |
if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); |
if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) |
mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) |
mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) |
mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) |
mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) |
mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) |
mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) |
mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) |
mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) |
mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) |
mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); |
if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) |
mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); |
if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); |
if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) |
mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); |
if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) |
mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); |
if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); |
if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); |
if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); |
if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); |
if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) ) |
mbedtls_snprintf( buf, buflen, "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" ); |
#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ |
// END generated code |
if( strlen( buf ) == 0 ) |
mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); |
} |
use_ret = ret & ~0xFF80; |
if( use_ret == 0 ) |
return; |
// If high level code is present, make a concatenation between both |
// error strings. |
// |
len = strlen( buf ); |
if( len > 0 ) |
{ |
if( buflen - len < 5 ) |
return; |
mbedtls_snprintf( buf + len, buflen - len, " : " ); |
buf += len + 3; |
buflen -= len + 3; |
} |
// Low level error codes |
// |
// BEGIN generated code |
#if defined(MBEDTLS_AES_C) |
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); |
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); |
if( use_ret == -(MBEDTLS_ERR_AES_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "AES - Invalid input data" ); |
if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" ); |
if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "AES - AES hardware accelerator failed" ); |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_ARC4_C) |
if( use_ret == -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" ); |
#endif /* MBEDTLS_ARC4_C */ |
#if defined(MBEDTLS_ARIA_C) |
if( use_ret == -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "ARIA - Bad input data" ); |
if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" ); |
if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "ARIA - Feature not available. For example, an unsupported ARIA key size" ); |
if( use_ret == -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ARIA - ARIA hardware accelerator failed" ); |
#endif /* MBEDTLS_ARIA_C */ |
#if defined(MBEDTLS_ASN1_PARSE_C) |
if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) |
mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); |
if( use_ret == -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) ) |
mbedtls_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); |
if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); |
if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) ) |
mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); |
if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) ) |
mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); |
if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); |
if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); |
#endif /* MBEDTLS_ASN1_PARSE_C */ |
#if defined(MBEDTLS_BASE64_C) |
if( use_ret == -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); |
if( use_ret == -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER) ) |
mbedtls_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); |
#endif /* MBEDTLS_BASE64_C */ |
#if defined(MBEDTLS_BIGNUM_C) |
if( use_ret == -(MBEDTLS_ERR_MPI_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); |
if( use_ret == -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_MPI_INVALID_CHARACTER) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); |
if( use_ret == -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); |
if( use_ret == -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); |
if( use_ret == -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); |
if( use_ret == -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); |
if( use_ret == -(MBEDTLS_ERR_MPI_ALLOC_FAILED) ) |
mbedtls_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); |
#endif /* MBEDTLS_BIGNUM_C */ |
#if defined(MBEDTLS_BLOWFISH_C) |
if( use_ret == -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "BLOWFISH - Bad input data" ); |
if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); |
if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); |
#endif /* MBEDTLS_BLOWFISH_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
if( use_ret == -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "CAMELLIA - Bad input data" ); |
if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); |
if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CAMELLIA - Camellia hardware accelerator failed" ); |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_CCM_C) |
if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) |
mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to the function" ); |
if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); |
if( use_ret == -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); |
#endif /* MBEDTLS_CCM_C */ |
#if defined(MBEDTLS_CHACHA20_C) |
if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" ); |
if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); |
if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" ); |
#endif /* MBEDTLS_CHACHA20_C */ |
#if defined(MBEDTLS_CHACHAPOLY_C) |
if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) ) |
mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" ); |
if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); |
#endif /* MBEDTLS_CHACHAPOLY_C */ |
#if defined(MBEDTLS_CMAC_C) |
if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); |
#endif /* MBEDTLS_CMAC_C */ |
#if defined(MBEDTLS_CTR_DRBG_C) |
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) |
mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); |
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) |
mbedtls_snprintf( buf, buflen, "CTR_DRBG - The requested random buffer length is too big" ); |
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) |
mbedtls_snprintf( buf, buflen, "CTR_DRBG - The input (entropy + additional data) is too large" ); |
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read or write error in file" ); |
#endif /* MBEDTLS_CTR_DRBG_C */ |
#if defined(MBEDTLS_DES_C) |
if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); |
if( use_ret == -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "DES - DES hardware accelerator failed" ); |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ENTROPY_C) |
if( use_ret == -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED) ) |
mbedtls_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); |
if( use_ret == -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES) ) |
mbedtls_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); |
if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED) ) |
mbedtls_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); |
if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE) ) |
mbedtls_snprintf( buf, buflen, "ENTROPY - No strong sources have been added to poll" ); |
if( use_ret == -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); |
#endif /* MBEDTLS_ENTROPY_C */ |
#if defined(MBEDTLS_GCM_C) |
if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) |
mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); |
if( use_ret == -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "GCM - GCM hardware accelerator failed" ); |
if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) |
mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_HKDF_C) |
if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" ); |
#endif /* MBEDTLS_HKDF_C */ |
#if defined(MBEDTLS_HMAC_DRBG_C) |
if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) |
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); |
if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) |
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); |
if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR) ) |
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); |
if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) |
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); |
#endif /* MBEDTLS_HMAC_DRBG_C */ |
#if defined(MBEDTLS_MD2_C) |
if( use_ret == -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "MD2 - MD2 hardware accelerator failed" ); |
#endif /* MBEDTLS_MD2_C */ |
#if defined(MBEDTLS_MD4_C) |
if( use_ret == -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "MD4 - MD4 hardware accelerator failed" ); |
#endif /* MBEDTLS_MD4_C */ |
#if defined(MBEDTLS_MD5_C) |
if( use_ret == -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" ); |
#endif /* MBEDTLS_MD5_C */ |
#if defined(MBEDTLS_NET_C) |
if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); |
if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); |
if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); |
if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); |
if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); |
if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); |
if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); |
if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) |
mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); |
if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) |
mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); |
if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); |
if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) |
mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); |
if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" ); |
if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "NET - Input invalid" ); |
#endif /* MBEDTLS_NET_C */ |
#if defined(MBEDTLS_OID_C) |
if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) |
mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); |
if( use_ret == -(MBEDTLS_ERR_OID_BUF_TOO_SMALL) ) |
mbedtls_snprintf( buf, buflen, "OID - output buffer is too small" ); |
#endif /* MBEDTLS_OID_C */ |
#if defined(MBEDTLS_PADLOCK_C) |
if( use_ret == -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED) ) |
mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); |
#endif /* MBEDTLS_PADLOCK_C */ |
#if defined(MBEDTLS_PLATFORM_C) |
if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" ); |
if( use_ret == -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) ) |
mbedtls_snprintf( buf, buflen, "PLATFORM - The requested feature is not supported by the platform" ); |
#endif /* MBEDTLS_PLATFORM_C */ |
#if defined(MBEDTLS_POLY1305_C) |
if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); |
if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); |
if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" ); |
#endif /* MBEDTLS_POLY1305_C */ |
#if defined(MBEDTLS_RIPEMD160_C) |
if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); |
#endif /* MBEDTLS_RIPEMD160_C */ |
#if defined(MBEDTLS_SHA1_C) |
if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" ); |
if( use_ret == -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 input data was malformed" ); |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" ); |
if( use_ret == -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 input data was malformed" ); |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" ); |
if( use_ret == -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 input data was malformed" ); |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_THREADING_C) |
if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) |
mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); |
if( use_ret == -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA) ) |
mbedtls_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); |
if( use_ret == -(MBEDTLS_ERR_THREADING_MUTEX_ERROR) ) |
mbedtls_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); |
#endif /* MBEDTLS_THREADING_C */ |
#if defined(MBEDTLS_XTEA_C) |
if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) |
mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); |
if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) ) |
mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" ); |
#endif /* MBEDTLS_XTEA_C */ |
// END generated code |
if( strlen( buf ) != 0 ) |
return; |
mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); |
} |
#else /* MBEDTLS_ERROR_C */ |
#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) |
/* |
* Provide an non-function in case MBEDTLS_ERROR_C is not defined |
*/ |
void mbedtls_strerror( int ret, char *buf, size_t buflen ) |
{ |
((void) ret); |
if( buflen > 0 ) |
buf[0] = '\0'; |
} |
#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ |
#endif /* MBEDTLS_ERROR_C */ |
/programs/develop/libraries/kos_mbedtls/library/gcm.c |
---|
0,0 → 1,996 |
/* |
* NIST SP800-38D compliant GCM implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf |
* |
* See also: |
* [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf |
* |
* We use the algorithm described as Shoup's method with 4-bit tables in |
* [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_GCM_C) |
#include "mbedtls/gcm.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_AESNI_C) |
#include "mbedtls/aesni.h" |
#endif |
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) |
#include "mbedtls/aes.h" |
#include "mbedtls/platform.h" |
#if !defined(MBEDTLS_PLATFORM_C) |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ |
#if !defined(MBEDTLS_GCM_ALT) |
/* Parameter validation macros */ |
#define GCM_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) |
#define GCM_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* 32-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} |
#endif |
/* |
* Initialize a context |
*/ |
void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) |
{ |
GCM_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); |
} |
/* |
* Precompute small multiples of H, that is set |
* HH[i] || HL[i] = H times i, |
* where i is seen as a field element as in [MGV], ie high-order bits |
* correspond to low powers of P. The result is stored in the same way, that |
* is the high-order bit of HH corresponds to P^0 and the low-order bit of HL |
* corresponds to P^127. |
*/ |
static int gcm_gen_table( mbedtls_gcm_context *ctx ) |
{ |
int ret, i, j; |
uint64_t hi, lo; |
uint64_t vl, vh; |
unsigned char h[16]; |
size_t olen = 0; |
memset( h, 0, 16 ); |
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) |
return( ret ); |
/* pack h as two 64-bits ints, big-endian */ |
GET_UINT32_BE( hi, h, 0 ); |
GET_UINT32_BE( lo, h, 4 ); |
vh = (uint64_t) hi << 32 | lo; |
GET_UINT32_BE( hi, h, 8 ); |
GET_UINT32_BE( lo, h, 12 ); |
vl = (uint64_t) hi << 32 | lo; |
/* 8 = 1000 corresponds to 1 in GF(2^128) */ |
ctx->HL[8] = vl; |
ctx->HH[8] = vh; |
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) |
/* With CLMUL support, we need only h, not the rest of the table */ |
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) |
return( 0 ); |
#endif |
/* 0 corresponds to 0 in GF(2^128) */ |
ctx->HH[0] = 0; |
ctx->HL[0] = 0; |
for( i = 4; i > 0; i >>= 1 ) |
{ |
uint32_t T = ( vl & 1 ) * 0xe1000000U; |
vl = ( vh << 63 ) | ( vl >> 1 ); |
vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); |
ctx->HL[i] = vl; |
ctx->HH[i] = vh; |
} |
for( i = 2; i <= 8; i *= 2 ) |
{ |
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; |
vh = *HiH; |
vl = *HiL; |
for( j = 1; j < i; j++ ) |
{ |
HiH[j] = vh ^ ctx->HH[j]; |
HiL[j] = vl ^ ctx->HL[j]; |
} |
} |
return( 0 ); |
} |
int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, |
mbedtls_cipher_id_t cipher, |
const unsigned char *key, |
unsigned int keybits ) |
{ |
int ret; |
const mbedtls_cipher_info_t *cipher_info; |
GCM_VALIDATE_RET( ctx != NULL ); |
GCM_VALIDATE_RET( key != NULL ); |
GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 ); |
cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); |
if( cipher_info == NULL ) |
return( MBEDTLS_ERR_GCM_BAD_INPUT ); |
if( cipher_info->block_size != 16 ) |
return( MBEDTLS_ERR_GCM_BAD_INPUT ); |
mbedtls_cipher_free( &ctx->cipher_ctx ); |
if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, |
MBEDTLS_ENCRYPT ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = gcm_gen_table( ctx ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
/* |
* Shoup's method for multiplication use this table with |
* last4[x] = x times P^128 |
* where x and last4[x] are seen as elements of GF(2^128) as in [MGV] |
*/ |
static const uint64_t last4[16] = |
{ |
0x0000, 0x1c20, 0x3840, 0x2460, |
0x7080, 0x6ca0, 0x48c0, 0x54e0, |
0xe100, 0xfd20, 0xd940, 0xc560, |
0x9180, 0x8da0, 0xa9c0, 0xb5e0 |
}; |
/* |
* Sets output to x times H using the precomputed tables. |
* x and output are seen as elements of GF(2^128) as in [MGV]. |
*/ |
static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], |
unsigned char output[16] ) |
{ |
int i = 0; |
unsigned char lo, hi, rem; |
uint64_t zh, zl; |
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) |
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { |
unsigned char h[16]; |
PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); |
PUT_UINT32_BE( ctx->HH[8], h, 4 ); |
PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); |
PUT_UINT32_BE( ctx->HL[8], h, 12 ); |
mbedtls_aesni_gcm_mult( output, x, h ); |
return; |
} |
#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ |
lo = x[15] & 0xf; |
zh = ctx->HH[lo]; |
zl = ctx->HL[lo]; |
for( i = 15; i >= 0; i-- ) |
{ |
lo = x[i] & 0xf; |
hi = x[i] >> 4; |
if( i != 15 ) |
{ |
rem = (unsigned char) zl & 0xf; |
zl = ( zh << 60 ) | ( zl >> 4 ); |
zh = ( zh >> 4 ); |
zh ^= (uint64_t) last4[rem] << 48; |
zh ^= ctx->HH[lo]; |
zl ^= ctx->HL[lo]; |
} |
rem = (unsigned char) zl & 0xf; |
zl = ( zh << 60 ) | ( zl >> 4 ); |
zh = ( zh >> 4 ); |
zh ^= (uint64_t) last4[rem] << 48; |
zh ^= ctx->HH[hi]; |
zl ^= ctx->HL[hi]; |
} |
PUT_UINT32_BE( zh >> 32, output, 0 ); |
PUT_UINT32_BE( zh, output, 4 ); |
PUT_UINT32_BE( zl >> 32, output, 8 ); |
PUT_UINT32_BE( zl, output, 12 ); |
} |
int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, |
int mode, |
const unsigned char *iv, |
size_t iv_len, |
const unsigned char *add, |
size_t add_len ) |
{ |
int ret; |
unsigned char work_buf[16]; |
size_t i; |
const unsigned char *p; |
size_t use_len, olen = 0; |
GCM_VALIDATE_RET( ctx != NULL ); |
GCM_VALIDATE_RET( iv != NULL ); |
GCM_VALIDATE_RET( add_len == 0 || add != NULL ); |
/* IV and AD are limited to 2^64 bits, so 2^61 bytes */ |
/* IV is not allowed to be zero length */ |
if( iv_len == 0 || |
( (uint64_t) iv_len ) >> 61 != 0 || |
( (uint64_t) add_len ) >> 61 != 0 ) |
{ |
return( MBEDTLS_ERR_GCM_BAD_INPUT ); |
} |
memset( ctx->y, 0x00, sizeof(ctx->y) ); |
memset( ctx->buf, 0x00, sizeof(ctx->buf) ); |
ctx->mode = mode; |
ctx->len = 0; |
ctx->add_len = 0; |
if( iv_len == 12 ) |
{ |
memcpy( ctx->y, iv, iv_len ); |
ctx->y[15] = 1; |
} |
else |
{ |
memset( work_buf, 0x00, 16 ); |
PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); |
p = iv; |
while( iv_len > 0 ) |
{ |
use_len = ( iv_len < 16 ) ? iv_len : 16; |
for( i = 0; i < use_len; i++ ) |
ctx->y[i] ^= p[i]; |
gcm_mult( ctx, ctx->y, ctx->y ); |
iv_len -= use_len; |
p += use_len; |
} |
for( i = 0; i < 16; i++ ) |
ctx->y[i] ^= work_buf[i]; |
gcm_mult( ctx, ctx->y, ctx->y ); |
} |
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, |
&olen ) ) != 0 ) |
{ |
return( ret ); |
} |
ctx->add_len = add_len; |
p = add; |
while( add_len > 0 ) |
{ |
use_len = ( add_len < 16 ) ? add_len : 16; |
for( i = 0; i < use_len; i++ ) |
ctx->buf[i] ^= p[i]; |
gcm_mult( ctx, ctx->buf, ctx->buf ); |
add_len -= use_len; |
p += use_len; |
} |
return( 0 ); |
} |
int mbedtls_gcm_update( mbedtls_gcm_context *ctx, |
size_t length, |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
unsigned char ectr[16]; |
size_t i; |
const unsigned char *p; |
unsigned char *out_p = output; |
size_t use_len, olen = 0; |
GCM_VALIDATE_RET( ctx != NULL ); |
GCM_VALIDATE_RET( length == 0 || input != NULL ); |
GCM_VALIDATE_RET( length == 0 || output != NULL ); |
if( output > input && (size_t) ( output - input ) < length ) |
return( MBEDTLS_ERR_GCM_BAD_INPUT ); |
/* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes |
* Also check for possible overflow */ |
if( ctx->len + length < ctx->len || |
(uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) |
{ |
return( MBEDTLS_ERR_GCM_BAD_INPUT ); |
} |
ctx->len += length; |
p = input; |
while( length > 0 ) |
{ |
use_len = ( length < 16 ) ? length : 16; |
for( i = 16; i > 12; i-- ) |
if( ++ctx->y[i - 1] != 0 ) |
break; |
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, |
&olen ) ) != 0 ) |
{ |
return( ret ); |
} |
for( i = 0; i < use_len; i++ ) |
{ |
if( ctx->mode == MBEDTLS_GCM_DECRYPT ) |
ctx->buf[i] ^= p[i]; |
out_p[i] = ectr[i] ^ p[i]; |
if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) |
ctx->buf[i] ^= out_p[i]; |
} |
gcm_mult( ctx, ctx->buf, ctx->buf ); |
length -= use_len; |
p += use_len; |
out_p += use_len; |
} |
return( 0 ); |
} |
int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, |
unsigned char *tag, |
size_t tag_len ) |
{ |
unsigned char work_buf[16]; |
size_t i; |
uint64_t orig_len; |
uint64_t orig_add_len; |
GCM_VALIDATE_RET( ctx != NULL ); |
GCM_VALIDATE_RET( tag != NULL ); |
orig_len = ctx->len * 8; |
orig_add_len = ctx->add_len * 8; |
if( tag_len > 16 || tag_len < 4 ) |
return( MBEDTLS_ERR_GCM_BAD_INPUT ); |
memcpy( tag, ctx->base_ectr, tag_len ); |
if( orig_len || orig_add_len ) |
{ |
memset( work_buf, 0x00, 16 ); |
PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); |
PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); |
PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); |
PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); |
for( i = 0; i < 16; i++ ) |
ctx->buf[i] ^= work_buf[i]; |
gcm_mult( ctx, ctx->buf, ctx->buf ); |
for( i = 0; i < tag_len; i++ ) |
tag[i] ^= ctx->buf[i]; |
} |
return( 0 ); |
} |
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, |
int mode, |
size_t length, |
const unsigned char *iv, |
size_t iv_len, |
const unsigned char *add, |
size_t add_len, |
const unsigned char *input, |
unsigned char *output, |
size_t tag_len, |
unsigned char *tag ) |
{ |
int ret; |
GCM_VALIDATE_RET( ctx != NULL ); |
GCM_VALIDATE_RET( iv != NULL ); |
GCM_VALIDATE_RET( add_len == 0 || add != NULL ); |
GCM_VALIDATE_RET( length == 0 || input != NULL ); |
GCM_VALIDATE_RET( length == 0 || output != NULL ); |
GCM_VALIDATE_RET( tag != NULL ); |
if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, |
size_t length, |
const unsigned char *iv, |
size_t iv_len, |
const unsigned char *add, |
size_t add_len, |
const unsigned char *tag, |
size_t tag_len, |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
unsigned char check_tag[16]; |
size_t i; |
int diff; |
GCM_VALIDATE_RET( ctx != NULL ); |
GCM_VALIDATE_RET( iv != NULL ); |
GCM_VALIDATE_RET( add_len == 0 || add != NULL ); |
GCM_VALIDATE_RET( tag != NULL ); |
GCM_VALIDATE_RET( length == 0 || input != NULL ); |
GCM_VALIDATE_RET( length == 0 || output != NULL ); |
if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, |
iv, iv_len, add, add_len, |
input, output, tag_len, check_tag ) ) != 0 ) |
{ |
return( ret ); |
} |
/* Check tag in "constant-time" */ |
for( diff = 0, i = 0; i < tag_len; i++ ) |
diff |= tag[i] ^ check_tag[i]; |
if( diff != 0 ) |
{ |
mbedtls_platform_zeroize( output, length ); |
return( MBEDTLS_ERR_GCM_AUTH_FAILED ); |
} |
return( 0 ); |
} |
void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_cipher_free( &ctx->cipher_ctx ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); |
} |
#endif /* !MBEDTLS_GCM_ALT */ |
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) |
/* |
* AES-GCM test vectors from: |
* |
* http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip |
*/ |
#define MAX_TESTS 6 |
static const int key_index[MAX_TESTS] = |
{ 0, 0, 1, 1, 1, 1 }; |
static const unsigned char key[MAX_TESTS][32] = |
{ |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
{ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, |
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, |
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, |
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, |
}; |
static const size_t iv_len[MAX_TESTS] = |
{ 12, 12, 12, 12, 8, 60 }; |
static const int iv_index[MAX_TESTS] = |
{ 0, 0, 1, 1, 1, 2 }; |
static const unsigned char iv[MAX_TESTS][64] = |
{ |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00 }, |
{ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, |
0xde, 0xca, 0xf8, 0x88 }, |
{ 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, |
0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, |
0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, |
0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, |
0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, |
0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, |
0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, |
0xa6, 0x37, 0xb3, 0x9b }, |
}; |
static const size_t add_len[MAX_TESTS] = |
{ 0, 0, 0, 20, 20, 20 }; |
static const int add_index[MAX_TESTS] = |
{ 0, 0, 0, 1, 1, 1 }; |
static const unsigned char additional[MAX_TESTS][64] = |
{ |
{ 0x00 }, |
{ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, |
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, |
0xab, 0xad, 0xda, 0xd2 }, |
}; |
static const size_t pt_len[MAX_TESTS] = |
{ 0, 16, 64, 60, 60, 60 }; |
static const int pt_index[MAX_TESTS] = |
{ 0, 0, 1, 1, 1, 1 }; |
static const unsigned char pt[MAX_TESTS][64] = |
{ |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, |
{ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, |
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, |
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, |
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, |
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, |
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, |
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, |
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, |
}; |
static const unsigned char ct[MAX_TESTS * 3][64] = |
{ |
{ 0x00 }, |
{ 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, |
0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, |
{ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, |
0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, |
0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, |
0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, |
0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, |
0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, |
0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, |
0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, |
{ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, |
0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, |
0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, |
0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, |
0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, |
0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, |
0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, |
0x3d, 0x58, 0xe0, 0x91 }, |
{ 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, |
0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, |
0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, |
0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, |
0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, |
0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, |
0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, |
0xc2, 0x3f, 0x45, 0x98 }, |
{ 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, |
0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, |
0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, |
0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, |
0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, |
0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, |
0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, |
0x4c, 0x34, 0xae, 0xe5 }, |
{ 0x00 }, |
{ 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, |
0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, |
{ 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, |
0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, |
0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, |
0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, |
0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, |
0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, |
0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, |
0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, |
{ 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, |
0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, |
0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, |
0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, |
0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, |
0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, |
0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, |
0xcc, 0xda, 0x27, 0x10 }, |
{ 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, |
0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, |
0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, |
0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, |
0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, |
0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, |
0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, |
0xa0, 0xf0, 0x62, 0xf7 }, |
{ 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, |
0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, |
0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, |
0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, |
0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, |
0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, |
0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, |
0xe9, 0xb7, 0x37, 0x3b }, |
{ 0x00 }, |
{ 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, |
0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, |
{ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, |
0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, |
0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, |
0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, |
0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, |
0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, |
0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, |
0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, |
{ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, |
0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, |
0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, |
0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, |
0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, |
0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, |
0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, |
0xbc, 0xc9, 0xf6, 0x62 }, |
{ 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, |
0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, |
0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, |
0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, |
0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, |
0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, |
0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, |
0xf4, 0x7c, 0x9b, 0x1f }, |
{ 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, |
0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, |
0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, |
0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, |
0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, |
0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, |
0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, |
0x44, 0xae, 0x7e, 0x3f }, |
}; |
static const unsigned char tag[MAX_TESTS * 3][16] = |
{ |
{ 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, |
0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, |
{ 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, |
0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, |
{ 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, |
0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, |
{ 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, |
0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, |
{ 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, |
0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, |
{ 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, |
0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, |
{ 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, |
0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, |
{ 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, |
0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, |
{ 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, |
0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, |
{ 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, |
0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, |
{ 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, |
0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, |
{ 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, |
0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, |
{ 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, |
0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, |
{ 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, |
0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, |
{ 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, |
0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, |
{ 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, |
0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, |
{ 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, |
0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, |
{ 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, |
0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, |
}; |
int mbedtls_gcm_self_test( int verbose ) |
{ |
mbedtls_gcm_context ctx; |
unsigned char buf[64]; |
unsigned char tag_buf[16]; |
int i, j, ret; |
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; |
for( j = 0; j < 3; j++ ) |
{ |
int key_len = 128 + 64 * j; |
for( i = 0; i < MAX_TESTS; i++ ) |
{ |
mbedtls_gcm_init( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( " AES-GCM-%3d #%d (%s): ", |
key_len, i, "enc" ); |
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], |
key_len ); |
/* |
* AES-192 is an optional feature that may be unavailable when |
* there is an alternative underlying implementation i.e. when |
* MBEDTLS_AES_ALT is defined. |
*/ |
if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 ) |
{ |
mbedtls_printf( "skipped\n" ); |
break; |
} |
else if( ret != 0 ) |
{ |
goto exit; |
} |
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, |
pt_len[i], |
iv[iv_index[i]], iv_len[i], |
additional[add_index[i]], add_len[i], |
pt[pt_index[i]], buf, 16, tag_buf ); |
if( ret != 0 ) |
goto exit; |
if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || |
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
mbedtls_gcm_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
mbedtls_gcm_init( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( " AES-GCM-%3d #%d (%s): ", |
key_len, i, "dec" ); |
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], |
key_len ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, |
pt_len[i], |
iv[iv_index[i]], iv_len[i], |
additional[add_index[i]], add_len[i], |
ct[j * 6 + i], buf, 16, tag_buf ); |
if( ret != 0 ) |
goto exit; |
if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || |
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
mbedtls_gcm_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
mbedtls_gcm_init( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", |
key_len, i, "enc" ); |
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], |
key_len ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, |
iv[iv_index[i]], iv_len[i], |
additional[add_index[i]], add_len[i] ); |
if( ret != 0 ) |
goto exit; |
if( pt_len[i] > 32 ) |
{ |
size_t rest_len = pt_len[i] - 32; |
ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, |
buf + 32 ); |
if( ret != 0 ) |
goto exit; |
} |
else |
{ |
ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); |
if( ret != 0 ) |
goto exit; |
} |
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); |
if( ret != 0 ) |
goto exit; |
if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || |
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
mbedtls_gcm_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
mbedtls_gcm_init( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", |
key_len, i, "dec" ); |
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], |
key_len ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, |
iv[iv_index[i]], iv_len[i], |
additional[add_index[i]], add_len[i] ); |
if( ret != 0 ) |
goto exit; |
if( pt_len[i] > 32 ) |
{ |
size_t rest_len = pt_len[i] - 32; |
ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, |
buf + 32 ); |
if( ret != 0 ) |
goto exit; |
} |
else |
{ |
ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], |
buf ); |
if( ret != 0 ) |
goto exit; |
} |
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); |
if( ret != 0 ) |
goto exit; |
if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || |
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
mbedtls_gcm_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
ret = 0; |
exit: |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
mbedtls_gcm_free( &ctx ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ |
#endif /* MBEDTLS_GCM_C */ |
/programs/develop/libraries/kos_mbedtls/library/havege.c |
---|
0,0 → 1,255 |
/** |
* \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The HAVEGE RNG was designed by Andre Seznec in 2002. |
* |
* http://www.irisa.fr/caps/projects/hipsor/publi.php |
* |
* Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_HAVEGE_C) |
#include "mbedtls/havege.h" |
#include "mbedtls/timing.h" |
#include "mbedtls/platform_util.h" |
#include <limits.h> |
#include <string.h> |
/* If int isn't capable of storing 2^32 distinct values, the code of this |
* module may cause a processor trap or a miscalculation. If int is more |
* than 32 bits, the code may not calculate the intended values. */ |
#if INT_MIN + 1 != -0x7fffffff |
#error "The HAVEGE module requires int to be exactly 32 bits, with INT_MIN = -2^31." |
#endif |
#if UINT_MAX != 0xffffffff |
#error "The HAVEGE module requires unsigned to be exactly 32 bits." |
#endif |
/* ------------------------------------------------------------------------ |
* On average, one iteration accesses two 8-word blocks in the havege WALK |
* table, and generates 16 words in the RES array. |
* |
* The data read in the WALK table is updated and permuted after each use. |
* The result of the hardware clock counter read is used for this update. |
* |
* 25 conditional tests are present. The conditional tests are grouped in |
* two nested groups of 12 conditional tests and 1 test that controls the |
* permutation; on average, there should be 6 tests executed and 3 of them |
* should be mispredicted. |
* ------------------------------------------------------------------------ |
*/ |
#define SWAP(X,Y) { unsigned *T = (X); (X) = (Y); (Y) = T; } |
#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; |
#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; |
#define TST1_LEAVE U1++; } |
#define TST2_LEAVE U2++; } |
#define ONE_ITERATION \ |
\ |
PTEST = PT1 >> 20; \ |
\ |
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ |
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ |
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ |
\ |
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ |
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ |
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ |
\ |
PTX = (PT1 >> 18) & 7; \ |
PT1 &= 0x1FFF; \ |
PT2 &= 0x1FFF; \ |
CLK = (unsigned) mbedtls_timing_hardclock(); \ |
\ |
i = 0; \ |
A = &WALK[PT1 ]; RES[i++] ^= *A; \ |
B = &WALK[PT2 ]; RES[i++] ^= *B; \ |
C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ |
D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ |
\ |
IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ |
*A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ |
*B = IN ^ U1; \ |
*C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ |
*D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ |
\ |
A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ |
B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ |
C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ |
D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ |
\ |
if( PTEST & 1 ) SWAP( A, C ); \ |
\ |
IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ |
*A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ |
*B = IN; CLK = (unsigned) mbedtls_timing_hardclock(); \ |
*C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ |
*D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ |
\ |
A = &WALK[PT1 ^ 4]; \ |
B = &WALK[PT2 ^ 1]; \ |
\ |
PTEST = PT2 >> 1; \ |
\ |
PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ |
PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ |
PTY = (PT2 >> 10) & 7; \ |
\ |
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ |
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ |
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ |
\ |
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ |
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ |
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ |
\ |
C = &WALK[PT1 ^ 5]; \ |
D = &WALK[PT2 ^ 5]; \ |
\ |
RES[i++] ^= *A; \ |
RES[i++] ^= *B; \ |
RES[i++] ^= *C; \ |
RES[i++] ^= *D; \ |
\ |
IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ |
*A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ |
*B = IN ^ U2; \ |
*C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ |
*D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ |
\ |
A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ |
B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ |
C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ |
D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ |
\ |
IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ |
*A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ |
*B = IN; \ |
*C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ |
*D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ |
\ |
PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ |
WALK[PT1 ^ PTX ^ 7] ) & (~1); \ |
PT1 ^= (PT2 ^ 0x10) & 0x10; \ |
\ |
for( n++, i = 0; i < 16; i++ ) \ |
POOL[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; |
/* |
* Entropy gathering function |
*/ |
static void havege_fill( mbedtls_havege_state *hs ) |
{ |
unsigned i, n = 0; |
unsigned U1, U2, *A, *B, *C, *D; |
unsigned PT1, PT2, *WALK, *POOL, RES[16]; |
unsigned PTX, PTY, CLK, PTEST, IN; |
WALK = (unsigned *) hs->WALK; |
POOL = (unsigned *) hs->pool; |
PT1 = hs->PT1; |
PT2 = hs->PT2; |
PTX = U1 = 0; |
PTY = U2 = 0; |
(void)PTX; |
memset( RES, 0, sizeof( RES ) ); |
while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) |
{ |
ONE_ITERATION |
ONE_ITERATION |
ONE_ITERATION |
ONE_ITERATION |
} |
hs->PT1 = PT1; |
hs->PT2 = PT2; |
hs->offset[0] = 0; |
hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; |
} |
/* |
* HAVEGE initialization |
*/ |
void mbedtls_havege_init( mbedtls_havege_state *hs ) |
{ |
memset( hs, 0, sizeof( mbedtls_havege_state ) ); |
havege_fill( hs ); |
} |
void mbedtls_havege_free( mbedtls_havege_state *hs ) |
{ |
if( hs == NULL ) |
return; |
mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) ); |
} |
/* |
* HAVEGE rand function |
*/ |
int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) |
{ |
int val; |
size_t use_len; |
mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; |
unsigned char *p = buf; |
while( len > 0 ) |
{ |
use_len = len; |
if( use_len > sizeof(int) ) |
use_len = sizeof(int); |
if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) |
havege_fill( hs ); |
val = hs->pool[hs->offset[0]++]; |
val ^= hs->pool[hs->offset[1]++]; |
memcpy( p, &val, use_len ); |
len -= use_len; |
p += use_len; |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_HAVEGE_C */ |
/programs/develop/libraries/kos_mbedtls/library/hkdf.c |
---|
0,0 → 1,194 |
/* |
* HKDF implementation -- RFC 5869 |
* |
* Copyright (C) 2016-2018, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_HKDF_C) |
#include <string.h> |
#include "mbedtls/hkdf.h" |
#include "mbedtls/platform_util.h" |
int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, |
size_t salt_len, const unsigned char *ikm, size_t ikm_len, |
const unsigned char *info, size_t info_len, |
unsigned char *okm, size_t okm_len ) |
{ |
int ret; |
unsigned char prk[MBEDTLS_MD_MAX_SIZE]; |
ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); |
if( ret == 0 ) |
{ |
ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), |
info, info_len, okm, okm_len ); |
} |
mbedtls_platform_zeroize( prk, sizeof( prk ) ); |
return( ret ); |
} |
int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, |
const unsigned char *salt, size_t salt_len, |
const unsigned char *ikm, size_t ikm_len, |
unsigned char *prk ) |
{ |
unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; |
if( salt == NULL ) |
{ |
size_t hash_len; |
if( salt_len != 0 ) |
{ |
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; |
} |
hash_len = mbedtls_md_get_size( md ); |
if( hash_len == 0 ) |
{ |
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; |
} |
salt = null_salt; |
salt_len = hash_len; |
} |
return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); |
} |
int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, |
size_t prk_len, const unsigned char *info, |
size_t info_len, unsigned char *okm, size_t okm_len ) |
{ |
size_t hash_len; |
size_t where = 0; |
size_t n; |
size_t t_len = 0; |
size_t i; |
int ret = 0; |
mbedtls_md_context_t ctx; |
unsigned char t[MBEDTLS_MD_MAX_SIZE]; |
if( okm == NULL ) |
{ |
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); |
} |
hash_len = mbedtls_md_get_size( md ); |
if( prk_len < hash_len || hash_len == 0 ) |
{ |
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); |
} |
if( info == NULL ) |
{ |
info = (const unsigned char *) ""; |
info_len = 0; |
} |
n = okm_len / hash_len; |
if( (okm_len % hash_len) != 0 ) |
{ |
n++; |
} |
/* |
* Per RFC 5869 Section 2.3, okm_len must not exceed |
* 255 times the hash length |
*/ |
if( n > 255 ) |
{ |
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); |
} |
mbedtls_md_init( &ctx ); |
if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) |
{ |
goto exit; |
} |
/* |
* Compute T = T(1) | T(2) | T(3) | ... | T(N) |
* Where T(N) is defined in RFC 5869 Section 2.3 |
*/ |
for( i = 1; i <= n; i++ ) |
{ |
size_t num_to_copy; |
unsigned char c = i & 0xff; |
ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); |
if( ret != 0 ) |
{ |
goto exit; |
} |
ret = mbedtls_md_hmac_update( &ctx, t, t_len ); |
if( ret != 0 ) |
{ |
goto exit; |
} |
ret = mbedtls_md_hmac_update( &ctx, info, info_len ); |
if( ret != 0 ) |
{ |
goto exit; |
} |
/* The constant concatenated to the end of each T(n) is a single octet. |
* */ |
ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); |
if( ret != 0 ) |
{ |
goto exit; |
} |
ret = mbedtls_md_hmac_finish( &ctx, t ); |
if( ret != 0 ) |
{ |
goto exit; |
} |
num_to_copy = i != n ? hash_len : okm_len - where; |
memcpy( okm + where, t, num_to_copy ); |
where += hash_len; |
t_len = hash_len; |
} |
exit: |
mbedtls_md_free( &ctx ); |
mbedtls_platform_zeroize( t, sizeof( t ) ); |
return( ret ); |
} |
#endif /* MBEDTLS_HKDF_C */ |
/programs/develop/libraries/kos_mbedtls/library/hmac_drbg.c |
---|
0,0 → 1,627 |
/* |
* HMAC_DRBG implementation (NIST SP 800-90) |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The NIST SP 800-90A DRBGs are described in the following publication. |
* http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf |
* References below are based on rev. 1 (January 2012). |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_HMAC_DRBG_C) |
#include "mbedtls/hmac_drbg.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_FS_IO) |
#include <stdio.h> |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_PLATFORM_C */ |
/* |
* HMAC_DRBG context initialization |
*/ |
void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &ctx->mutex ); |
#endif |
} |
/* |
* HMAC_DRBG update, using optional additional data (10.1.2.2) |
*/ |
int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, |
const unsigned char *additional, |
size_t add_len ) |
{ |
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); |
unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; |
unsigned char sep[1]; |
unsigned char K[MBEDTLS_MD_MAX_SIZE]; |
int ret; |
for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) |
{ |
/* Step 1 or 4 */ |
if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, |
ctx->V, md_len ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, |
sep, 1 ) ) != 0 ) |
goto exit; |
if( rounds == 2 ) |
{ |
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, |
additional, add_len ) ) != 0 ) |
goto exit; |
} |
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) |
goto exit; |
/* Step 2 or 5 */ |
if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, |
ctx->V, md_len ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) |
goto exit; |
} |
exit: |
mbedtls_platform_zeroize( K, sizeof( K ) ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, |
const unsigned char *additional, |
size_t add_len ) |
{ |
(void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); |
} |
#endif /* MBEDTLS_DEPRECATED_REMOVED */ |
/* |
* Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) |
*/ |
int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, |
const mbedtls_md_info_t * md_info, |
const unsigned char *data, size_t data_len ) |
{ |
int ret; |
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) |
return( ret ); |
/* |
* Set initial working state. |
* Use the V memory location, which is currently all 0, to initialize the |
* MD context with an all-zero key. Then set V to its initial value. |
*/ |
if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, |
mbedtls_md_get_size( md_info ) ) ) != 0 ) |
return( ret ); |
memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); |
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
/* |
* Internal function used both for seeding and reseeding the DRBG. |
* Comments starting with arabic numbers refer to section 10.1.2.4 |
* of SP800-90A, while roman numbers refer to section 9.2. |
*/ |
static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx, |
const unsigned char *additional, size_t len, |
int use_nonce ) |
{ |
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; |
size_t seedlen = 0; |
int ret; |
{ |
size_t total_entropy_len; |
if( use_nonce == 0 ) |
total_entropy_len = ctx->entropy_len; |
else |
total_entropy_len = ctx->entropy_len * 3 / 2; |
/* III. Check input length */ |
if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || |
total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) |
{ |
return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); |
} |
} |
memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); |
/* IV. Gather entropy_len bytes of entropy for the seed */ |
if( ( ret = ctx->f_entropy( ctx->p_entropy, |
seed, ctx->entropy_len ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); |
} |
seedlen += ctx->entropy_len; |
/* For initial seeding, allow adding of nonce generated |
* from the entropy source. See Sect 8.6.7 in SP800-90A. */ |
if( use_nonce ) |
{ |
/* Note: We don't merge the two calls to f_entropy() in order |
* to avoid requesting too much entropy from f_entropy() |
* at once. Specifically, if the underlying digest is not |
* SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which |
* is larger than the maximum of 32 Bytes that our own |
* entropy source implementation can emit in a single |
* call in configurations disabling SHA-512. */ |
if( ( ret = ctx->f_entropy( ctx->p_entropy, |
seed + seedlen, |
ctx->entropy_len / 2 ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); |
} |
seedlen += ctx->entropy_len / 2; |
} |
/* 1. Concatenate entropy and additional data if any */ |
if( additional != NULL && len != 0 ) |
{ |
memcpy( seed + seedlen, additional, len ); |
seedlen += len; |
} |
/* 2. Update state */ |
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) |
goto exit; |
/* 3. Reset reseed_counter */ |
ctx->reseed_counter = 1; |
exit: |
/* 4. Done */ |
mbedtls_platform_zeroize( seed, seedlen ); |
return( ret ); |
} |
/* |
* HMAC_DRBG reseeding: 10.1.2.4 + 9.2 |
*/ |
int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, |
const unsigned char *additional, size_t len ) |
{ |
return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) ); |
} |
/* |
* HMAC_DRBG initialisation (10.1.2.3 + 9.1) |
* |
* The nonce is not passed as a separate parameter but extracted |
* from the entropy source as suggested in 8.6.7. |
*/ |
int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, |
const mbedtls_md_info_t * md_info, |
int (*f_entropy)(void *, unsigned char *, size_t), |
void *p_entropy, |
const unsigned char *custom, |
size_t len ) |
{ |
int ret; |
size_t md_size; |
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) |
return( ret ); |
md_size = mbedtls_md_get_size( md_info ); |
/* |
* Set initial working state. |
* Use the V memory location, which is currently all 0, to initialize the |
* MD context with an all-zero key. Then set V to its initial value. |
*/ |
if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) |
return( ret ); |
memset( ctx->V, 0x01, md_size ); |
ctx->f_entropy = f_entropy; |
ctx->p_entropy = p_entropy; |
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; |
if( ctx->entropy_len == 0 ) |
{ |
/* |
* See SP800-57 5.6.1 (p. 65-66) for the security strength provided by |
* each hash function, then according to SP800-90A rev1 10.1 table 2, |
* min_entropy_len (in bits) is security_strength. |
* |
* (This also matches the sizes used in the NIST test vectors.) |
*/ |
ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ |
md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ |
32; /* better (256+) -> 256 bits */ |
} |
if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, |
1 /* add nonce */ ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
/* |
* Set prediction resistance |
*/ |
void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, |
int resistance ) |
{ |
ctx->prediction_resistance = resistance; |
} |
/* |
* Set entropy length grabbed for seeding |
*/ |
void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) |
{ |
ctx->entropy_len = len; |
} |
/* |
* Set reseed interval |
*/ |
void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) |
{ |
ctx->reseed_interval = interval; |
} |
/* |
* HMAC_DRBG random function with optional additional data: |
* 10.1.2.5 (arabic) + 9.3 (Roman) |
*/ |
int mbedtls_hmac_drbg_random_with_add( void *p_rng, |
unsigned char *output, size_t out_len, |
const unsigned char *additional, size_t add_len ) |
{ |
int ret; |
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; |
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); |
size_t left = out_len; |
unsigned char *out = output; |
/* II. Check request length */ |
if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) |
return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); |
/* III. Check input length */ |
if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) |
return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); |
/* 1. (aka VII and IX) Check reseed counter and PR */ |
if( ctx->f_entropy != NULL && /* For no-reseeding instances */ |
( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || |
ctx->reseed_counter > ctx->reseed_interval ) ) |
{ |
if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) |
return( ret ); |
add_len = 0; /* VII.4 */ |
} |
/* 2. Use additional data if any */ |
if( additional != NULL && add_len != 0 ) |
{ |
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, |
additional, add_len ) ) != 0 ) |
goto exit; |
} |
/* 3, 4, 5. Generate bytes */ |
while( left != 0 ) |
{ |
size_t use_len = left > md_len ? md_len : left; |
if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, |
ctx->V, md_len ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) |
goto exit; |
memcpy( out, ctx->V, use_len ); |
out += use_len; |
left -= use_len; |
} |
/* 6. Update */ |
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, |
additional, add_len ) ) != 0 ) |
goto exit; |
/* 7. Update reseed counter */ |
ctx->reseed_counter++; |
exit: |
/* 8. Done */ |
return( ret ); |
} |
/* |
* HMAC_DRBG random function |
*/ |
int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) |
{ |
int ret; |
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
/* |
* Free an HMAC_DRBG context |
*/ |
void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &ctx->mutex ); |
#endif |
mbedtls_md_free( &ctx->md_ctx ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); |
} |
#if defined(MBEDTLS_FS_IO) |
int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) |
{ |
int ret; |
FILE *f; |
unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; |
if( ( f = fopen( path, "wb" ) ) == NULL ) |
return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); |
if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) |
goto exit; |
if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) |
{ |
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; |
goto exit; |
} |
ret = 0; |
exit: |
fclose( f ); |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
return( ret ); |
} |
int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) |
{ |
int ret = 0; |
FILE *f = NULL; |
size_t n; |
unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; |
unsigned char c; |
if( ( f = fopen( path, "rb" ) ) == NULL ) |
return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); |
n = fread( buf, 1, sizeof( buf ), f ); |
if( fread( &c, 1, 1, f ) != 0 ) |
{ |
ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; |
goto exit; |
} |
if( n == 0 || ferror( f ) ) |
{ |
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; |
goto exit; |
} |
fclose( f ); |
f = NULL; |
ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n ); |
exit: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
if( f != NULL ) |
fclose( f ); |
if( ret != 0 ) |
return( ret ); |
return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); |
} |
#endif /* MBEDTLS_FS_IO */ |
#if defined(MBEDTLS_SELF_TEST) |
#if !defined(MBEDTLS_SHA1_C) |
/* Dummy checkup routine */ |
int mbedtls_hmac_drbg_self_test( int verbose ) |
{ |
(void) verbose; |
return( 0 ); |
} |
#else |
#define OUTPUT_LEN 80 |
/* From a NIST PR=true test vector */ |
static const unsigned char entropy_pr[] = { |
0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, |
0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, |
0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, |
0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, |
0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; |
static const unsigned char result_pr[OUTPUT_LEN] = { |
0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, |
0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, |
0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, |
0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, |
0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, |
0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, |
0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; |
/* From a NIST PR=false test vector */ |
static const unsigned char entropy_nopr[] = { |
0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, |
0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, |
0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, |
0xe9, 0x9d, 0xfe, 0xdf }; |
static const unsigned char result_nopr[OUTPUT_LEN] = { |
0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, |
0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, |
0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, |
0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, |
0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, |
0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, |
0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; |
/* "Entropy" from buffer */ |
static size_t test_offset; |
static int hmac_drbg_self_test_entropy( void *data, |
unsigned char *buf, size_t len ) |
{ |
const unsigned char *p = data; |
memcpy( buf, p + test_offset, len ); |
test_offset += len; |
return( 0 ); |
} |
#define CHK( c ) if( (c) != 0 ) \ |
{ \ |
if( verbose != 0 ) \ |
mbedtls_printf( "failed\n" ); \ |
return( 1 ); \ |
} |
/* |
* Checkup routine for HMAC_DRBG with SHA-1 |
*/ |
int mbedtls_hmac_drbg_self_test( int verbose ) |
{ |
mbedtls_hmac_drbg_context ctx; |
unsigned char buf[OUTPUT_LEN]; |
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); |
mbedtls_hmac_drbg_init( &ctx ); |
/* |
* PR = True |
*/ |
if( verbose != 0 ) |
mbedtls_printf( " HMAC_DRBG (PR = True) : " ); |
test_offset = 0; |
CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, |
hmac_drbg_self_test_entropy, (void *) entropy_pr, |
NULL, 0 ) ); |
mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); |
CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); |
CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); |
CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); |
mbedtls_hmac_drbg_free( &ctx ); |
mbedtls_hmac_drbg_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
/* |
* PR = False |
*/ |
if( verbose != 0 ) |
mbedtls_printf( " HMAC_DRBG (PR = False) : " ); |
mbedtls_hmac_drbg_init( &ctx ); |
test_offset = 0; |
CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, |
hmac_drbg_self_test_entropy, (void *) entropy_nopr, |
NULL, 0 ) ); |
CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); |
CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); |
CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); |
CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); |
mbedtls_hmac_drbg_free( &ctx ); |
mbedtls_hmac_drbg_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_HMAC_DRBG_C */ |
/programs/develop/libraries/kos_mbedtls/library/md.c |
---|
0,0 → 1,477 |
/** |
* \file mbedtls_md.c |
* |
* \brief Generic message digest wrapper for mbed TLS |
* |
* \author Adriaan de Jong <dejong@fox-it.com> |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_MD_C) |
#include "mbedtls/md.h" |
#include "mbedtls/md_internal.h" |
#include "mbedtls/platform_util.h" |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include <string.h> |
#if defined(MBEDTLS_FS_IO) |
#include <stdio.h> |
#endif |
/* |
* Reminder: update profiles in x509_crt.c when adding a new hash! |
*/ |
static const int supported_digests[] = { |
#if defined(MBEDTLS_SHA512_C) |
MBEDTLS_MD_SHA512, |
MBEDTLS_MD_SHA384, |
#endif |
#if defined(MBEDTLS_SHA256_C) |
MBEDTLS_MD_SHA256, |
MBEDTLS_MD_SHA224, |
#endif |
#if defined(MBEDTLS_SHA1_C) |
MBEDTLS_MD_SHA1, |
#endif |
#if defined(MBEDTLS_RIPEMD160_C) |
MBEDTLS_MD_RIPEMD160, |
#endif |
#if defined(MBEDTLS_MD5_C) |
MBEDTLS_MD_MD5, |
#endif |
#if defined(MBEDTLS_MD4_C) |
MBEDTLS_MD_MD4, |
#endif |
#if defined(MBEDTLS_MD2_C) |
MBEDTLS_MD_MD2, |
#endif |
MBEDTLS_MD_NONE |
}; |
const int *mbedtls_md_list( void ) |
{ |
return( supported_digests ); |
} |
const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) |
{ |
if( NULL == md_name ) |
return( NULL ); |
/* Get the appropriate digest information */ |
#if defined(MBEDTLS_MD2_C) |
if( !strcmp( "MD2", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); |
#endif |
#if defined(MBEDTLS_MD4_C) |
if( !strcmp( "MD4", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); |
#endif |
#if defined(MBEDTLS_MD5_C) |
if( !strcmp( "MD5", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); |
#endif |
#if defined(MBEDTLS_RIPEMD160_C) |
if( !strcmp( "RIPEMD160", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); |
#endif |
#if defined(MBEDTLS_SHA1_C) |
if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); |
#endif |
#if defined(MBEDTLS_SHA256_C) |
if( !strcmp( "SHA224", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); |
if( !strcmp( "SHA256", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
if( !strcmp( "SHA384", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); |
if( !strcmp( "SHA512", md_name ) ) |
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); |
#endif |
return( NULL ); |
} |
const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) |
{ |
switch( md_type ) |
{ |
#if defined(MBEDTLS_MD2_C) |
case MBEDTLS_MD_MD2: |
return( &mbedtls_md2_info ); |
#endif |
#if defined(MBEDTLS_MD4_C) |
case MBEDTLS_MD_MD4: |
return( &mbedtls_md4_info ); |
#endif |
#if defined(MBEDTLS_MD5_C) |
case MBEDTLS_MD_MD5: |
return( &mbedtls_md5_info ); |
#endif |
#if defined(MBEDTLS_RIPEMD160_C) |
case MBEDTLS_MD_RIPEMD160: |
return( &mbedtls_ripemd160_info ); |
#endif |
#if defined(MBEDTLS_SHA1_C) |
case MBEDTLS_MD_SHA1: |
return( &mbedtls_sha1_info ); |
#endif |
#if defined(MBEDTLS_SHA256_C) |
case MBEDTLS_MD_SHA224: |
return( &mbedtls_sha224_info ); |
case MBEDTLS_MD_SHA256: |
return( &mbedtls_sha256_info ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
case MBEDTLS_MD_SHA384: |
return( &mbedtls_sha384_info ); |
case MBEDTLS_MD_SHA512: |
return( &mbedtls_sha512_info ); |
#endif |
default: |
return( NULL ); |
} |
} |
void mbedtls_md_init( mbedtls_md_context_t *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); |
} |
void mbedtls_md_free( mbedtls_md_context_t *ctx ) |
{ |
if( ctx == NULL || ctx->md_info == NULL ) |
return; |
if( ctx->md_ctx != NULL ) |
ctx->md_info->ctx_free_func( ctx->md_ctx ); |
if( ctx->hmac_ctx != NULL ) |
{ |
mbedtls_platform_zeroize( ctx->hmac_ctx, |
2 * ctx->md_info->block_size ); |
mbedtls_free( ctx->hmac_ctx ); |
} |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); |
} |
int mbedtls_md_clone( mbedtls_md_context_t *dst, |
const mbedtls_md_context_t *src ) |
{ |
if( dst == NULL || dst->md_info == NULL || |
src == NULL || src->md_info == NULL || |
dst->md_info != src->md_info ) |
{ |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
} |
dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); |
return( 0 ); |
} |
#if ! defined(MBEDTLS_DEPRECATED_REMOVED) |
int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) |
{ |
return mbedtls_md_setup( ctx, md_info, 1 ); |
} |
#endif |
int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) |
{ |
if( md_info == NULL || ctx == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) |
return( MBEDTLS_ERR_MD_ALLOC_FAILED ); |
if( hmac != 0 ) |
{ |
ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); |
if( ctx->hmac_ctx == NULL ) |
{ |
md_info->ctx_free_func( ctx->md_ctx ); |
return( MBEDTLS_ERR_MD_ALLOC_FAILED ); |
} |
} |
ctx->md_info = md_info; |
return( 0 ); |
} |
int mbedtls_md_starts( mbedtls_md_context_t *ctx ) |
{ |
if( ctx == NULL || ctx->md_info == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
return( ctx->md_info->starts_func( ctx->md_ctx ) ); |
} |
int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) |
{ |
if( ctx == NULL || ctx->md_info == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); |
} |
int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) |
{ |
if( ctx == NULL || ctx->md_info == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); |
} |
int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, |
unsigned char *output ) |
{ |
if( md_info == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
return( md_info->digest_func( input, ilen, output ) ); |
} |
#if defined(MBEDTLS_FS_IO) |
int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) |
{ |
int ret; |
FILE *f; |
size_t n; |
mbedtls_md_context_t ctx; |
unsigned char buf[1024]; |
if( md_info == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
if( ( f = fopen( path, "rb" ) ) == NULL ) |
return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); |
mbedtls_md_init( &ctx ); |
if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) |
goto cleanup; |
if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 ) |
goto cleanup; |
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) |
if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 ) |
goto cleanup; |
if( ferror( f ) != 0 ) |
ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; |
else |
ret = md_info->finish_func( ctx.md_ctx, output ); |
cleanup: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
fclose( f ); |
mbedtls_md_free( &ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_FS_IO */ |
int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) |
{ |
int ret; |
unsigned char sum[MBEDTLS_MD_MAX_SIZE]; |
unsigned char *ipad, *opad; |
size_t i; |
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
if( keylen > (size_t) ctx->md_info->block_size ) |
{ |
if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) |
goto cleanup; |
if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 ) |
goto cleanup; |
if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 ) |
goto cleanup; |
keylen = ctx->md_info->size; |
key = sum; |
} |
ipad = (unsigned char *) ctx->hmac_ctx; |
opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; |
memset( ipad, 0x36, ctx->md_info->block_size ); |
memset( opad, 0x5C, ctx->md_info->block_size ); |
for( i = 0; i < keylen; i++ ) |
{ |
ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); |
opad[i] = (unsigned char)( opad[i] ^ key[i] ); |
} |
if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) |
goto cleanup; |
if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad, |
ctx->md_info->block_size ) ) != 0 ) |
goto cleanup; |
cleanup: |
mbedtls_platform_zeroize( sum, sizeof( sum ) ); |
return( ret ); |
} |
int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) |
{ |
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); |
} |
int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) |
{ |
int ret; |
unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; |
unsigned char *opad; |
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; |
if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 ) |
return( ret ); |
if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) |
return( ret ); |
if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad, |
ctx->md_info->block_size ) ) != 0 ) |
return( ret ); |
if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp, |
ctx->md_info->size ) ) != 0 ) |
return( ret ); |
return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); |
} |
int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) |
{ |
int ret; |
unsigned char *ipad; |
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
ipad = (unsigned char *) ctx->hmac_ctx; |
if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) |
return( ret ); |
return( ctx->md_info->update_func( ctx->md_ctx, ipad, |
ctx->md_info->block_size ) ); |
} |
int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, |
const unsigned char *key, size_t keylen, |
const unsigned char *input, size_t ilen, |
unsigned char *output ) |
{ |
mbedtls_md_context_t ctx; |
int ret; |
if( md_info == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
mbedtls_md_init( &ctx ); |
if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) |
goto cleanup; |
if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) |
goto cleanup; |
if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) |
goto cleanup; |
if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) |
goto cleanup; |
cleanup: |
mbedtls_md_free( &ctx ); |
return( ret ); |
} |
int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) |
{ |
if( ctx == NULL || ctx->md_info == NULL ) |
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); |
return( ctx->md_info->process_func( ctx->md_ctx, data ) ); |
} |
unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) |
{ |
if( md_info == NULL ) |
return( 0 ); |
return md_info->size; |
} |
mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) |
{ |
if( md_info == NULL ) |
return( MBEDTLS_MD_NONE ); |
return md_info->type; |
} |
const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) |
{ |
if( md_info == NULL ) |
return( NULL ); |
return md_info->name; |
} |
#endif /* MBEDTLS_MD_C */ |
/programs/develop/libraries/kos_mbedtls/library/md2.c |
---|
0,0 → 1,365 |
/* |
* RFC 1115/1319 compliant MD2 implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The MD2 algorithm was designed by Ron Rivest in 1989. |
* |
* http://www.ietf.org/rfc/rfc1115.txt |
* http://www.ietf.org/rfc/rfc1319.txt |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_MD2_C) |
#include "mbedtls/md2.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_MD2_ALT) |
static const unsigned char PI_SUBST[256] = |
{ |
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, |
0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, |
0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, |
0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, |
0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, |
0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, |
0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, |
0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, |
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, |
0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, |
0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, |
0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, |
0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, |
0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, |
0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, |
0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, |
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, |
0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, |
0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, |
0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, |
0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, |
0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, |
0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, |
0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, |
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, |
0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 |
}; |
void mbedtls_md2_init( mbedtls_md2_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_md2_context ) ); |
} |
void mbedtls_md2_free( mbedtls_md2_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) ); |
} |
void mbedtls_md2_clone( mbedtls_md2_context *dst, |
const mbedtls_md2_context *src ) |
{ |
*dst = *src; |
} |
/* |
* MD2 context setup |
*/ |
int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ) |
{ |
memset( ctx->cksum, 0, 16 ); |
memset( ctx->state, 0, 46 ); |
memset( ctx->buffer, 0, 16 ); |
ctx->left = 0; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md2_starts( mbedtls_md2_context *ctx ) |
{ |
mbedtls_md2_starts_ret( ctx ); |
} |
#endif |
#if !defined(MBEDTLS_MD2_PROCESS_ALT) |
int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ) |
{ |
int i, j; |
unsigned char t = 0; |
for( i = 0; i < 16; i++ ) |
{ |
ctx->state[i + 16] = ctx->buffer[i]; |
ctx->state[i + 32] = |
(unsigned char)( ctx->buffer[i] ^ ctx->state[i]); |
} |
for( i = 0; i < 18; i++ ) |
{ |
for( j = 0; j < 48; j++ ) |
{ |
ctx->state[j] = (unsigned char) |
( ctx->state[j] ^ PI_SUBST[t] ); |
t = ctx->state[j]; |
} |
t = (unsigned char)( t + i ); |
} |
t = ctx->cksum[15]; |
for( i = 0; i < 16; i++ ) |
{ |
ctx->cksum[i] = (unsigned char) |
( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); |
t = ctx->cksum[i]; |
} |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md2_process( mbedtls_md2_context *ctx ) |
{ |
mbedtls_internal_md2_process( ctx ); |
} |
#endif |
#endif /* !MBEDTLS_MD2_PROCESS_ALT */ |
/* |
* MD2 process buffer |
*/ |
int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
int ret; |
size_t fill; |
while( ilen > 0 ) |
{ |
if( ilen > 16 - ctx->left ) |
fill = 16 - ctx->left; |
else |
fill = ilen; |
memcpy( ctx->buffer + ctx->left, input, fill ); |
ctx->left += fill; |
input += fill; |
ilen -= fill; |
if( ctx->left == 16 ) |
{ |
ctx->left = 0; |
if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) |
return( ret ); |
} |
} |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md2_update( mbedtls_md2_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
mbedtls_md2_update_ret( ctx, input, ilen ); |
} |
#endif |
/* |
* MD2 final digest |
*/ |
int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, |
unsigned char output[16] ) |
{ |
int ret; |
size_t i; |
unsigned char x; |
x = (unsigned char)( 16 - ctx->left ); |
for( i = ctx->left; i < 16; i++ ) |
ctx->buffer[i] = x; |
if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) |
return( ret ); |
memcpy( ctx->buffer, ctx->cksum, 16 ); |
if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) |
return( ret ); |
memcpy( output, ctx->state, 16 ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md2_finish( mbedtls_md2_context *ctx, |
unsigned char output[16] ) |
{ |
mbedtls_md2_finish_ret( ctx, output ); |
} |
#endif |
#endif /* !MBEDTLS_MD2_ALT */ |
/* |
* output = MD2( input buffer ) |
*/ |
int mbedtls_md2_ret( const unsigned char *input, |
size_t ilen, |
unsigned char output[16] ) |
{ |
int ret; |
mbedtls_md2_context ctx; |
mbedtls_md2_init( &ctx ); |
if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_md2_free( &ctx ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md2( const unsigned char *input, |
size_t ilen, |
unsigned char output[16] ) |
{ |
mbedtls_md2_ret( input, ilen, output ); |
} |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* RFC 1319 test vectors |
*/ |
static const unsigned char md2_test_str[7][81] = |
{ |
{ "" }, |
{ "a" }, |
{ "abc" }, |
{ "message digest" }, |
{ "abcdefghijklmnopqrstuvwxyz" }, |
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, |
{ "12345678901234567890123456789012345678901234567890123456789012" |
"345678901234567890" } |
}; |
static const size_t md2_test_strlen[7] = |
{ |
0, 1, 3, 14, 26, 62, 80 |
}; |
static const unsigned char md2_test_sum[7][16] = |
{ |
{ 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, |
0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, |
{ 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, |
0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, |
{ 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, |
0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, |
{ 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, |
0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, |
{ 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, |
0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, |
{ 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, |
0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, |
{ 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, |
0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_md2_self_test( int verbose ) |
{ |
int i, ret = 0; |
unsigned char md2sum[16]; |
for( i = 0; i < 7; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " MD2 test #%d: ", i + 1 ); |
ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum ); |
if( ret != 0 ) |
goto fail; |
if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) |
{ |
ret = 1; |
goto fail; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
fail: |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_MD2_C */ |
/programs/develop/libraries/kos_mbedtls/library/md4.c |
---|
0,0 → 1,486 |
/* |
* RFC 1186/1320 compliant MD4 implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The MD4 algorithm was designed by Ron Rivest in 1990. |
* |
* http://www.ietf.org/rfc/rfc1186.txt |
* http://www.ietf.org/rfc/rfc1320.txt |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_MD4_C) |
#include "mbedtls/md4.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_MD4_ALT) |
/* |
* 32-bit integer manipulation macros (little endian) |
*/ |
#ifndef GET_UINT32_LE |
#define GET_UINT32_LE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] ) \ |
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 3] << 24 ); \ |
} |
#endif |
#ifndef PUT_UINT32_LE |
#define PUT_UINT32_LE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ |
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ |
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ |
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ |
} |
#endif |
void mbedtls_md4_init( mbedtls_md4_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_md4_context ) ); |
} |
void mbedtls_md4_free( mbedtls_md4_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) ); |
} |
void mbedtls_md4_clone( mbedtls_md4_context *dst, |
const mbedtls_md4_context *src ) |
{ |
*dst = *src; |
} |
/* |
* MD4 context setup |
*/ |
int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) |
{ |
ctx->total[0] = 0; |
ctx->total[1] = 0; |
ctx->state[0] = 0x67452301; |
ctx->state[1] = 0xEFCDAB89; |
ctx->state[2] = 0x98BADCFE; |
ctx->state[3] = 0x10325476; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md4_starts( mbedtls_md4_context *ctx ) |
{ |
mbedtls_md4_starts_ret( ctx ); |
} |
#endif |
#if !defined(MBEDTLS_MD4_PROCESS_ALT) |
int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, |
const unsigned char data[64] ) |
{ |
uint32_t X[16], A, B, C, D; |
GET_UINT32_LE( X[ 0], data, 0 ); |
GET_UINT32_LE( X[ 1], data, 4 ); |
GET_UINT32_LE( X[ 2], data, 8 ); |
GET_UINT32_LE( X[ 3], data, 12 ); |
GET_UINT32_LE( X[ 4], data, 16 ); |
GET_UINT32_LE( X[ 5], data, 20 ); |
GET_UINT32_LE( X[ 6], data, 24 ); |
GET_UINT32_LE( X[ 7], data, 28 ); |
GET_UINT32_LE( X[ 8], data, 32 ); |
GET_UINT32_LE( X[ 9], data, 36 ); |
GET_UINT32_LE( X[10], data, 40 ); |
GET_UINT32_LE( X[11], data, 44 ); |
GET_UINT32_LE( X[12], data, 48 ); |
GET_UINT32_LE( X[13], data, 52 ); |
GET_UINT32_LE( X[14], data, 56 ); |
GET_UINT32_LE( X[15], data, 60 ); |
#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) |
A = ctx->state[0]; |
B = ctx->state[1]; |
C = ctx->state[2]; |
D = ctx->state[3]; |
#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) |
#define P(a,b,c,d,x,s) \ |
do \ |
{ \ |
(a) += F((b),(c),(d)) + (x); \ |
(a) = S((a),(s)); \ |
} while( 0 ) |
P( A, B, C, D, X[ 0], 3 ); |
P( D, A, B, C, X[ 1], 7 ); |
P( C, D, A, B, X[ 2], 11 ); |
P( B, C, D, A, X[ 3], 19 ); |
P( A, B, C, D, X[ 4], 3 ); |
P( D, A, B, C, X[ 5], 7 ); |
P( C, D, A, B, X[ 6], 11 ); |
P( B, C, D, A, X[ 7], 19 ); |
P( A, B, C, D, X[ 8], 3 ); |
P( D, A, B, C, X[ 9], 7 ); |
P( C, D, A, B, X[10], 11 ); |
P( B, C, D, A, X[11], 19 ); |
P( A, B, C, D, X[12], 3 ); |
P( D, A, B, C, X[13], 7 ); |
P( C, D, A, B, X[14], 11 ); |
P( B, C, D, A, X[15], 19 ); |
#undef P |
#undef F |
#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) |
#define P(a,b,c,d,x,s) \ |
do \ |
{ \ |
(a) += F((b),(c),(d)) + (x) + 0x5A827999; \ |
(a) = S((a),(s)); \ |
} while( 0 ) |
P( A, B, C, D, X[ 0], 3 ); |
P( D, A, B, C, X[ 4], 5 ); |
P( C, D, A, B, X[ 8], 9 ); |
P( B, C, D, A, X[12], 13 ); |
P( A, B, C, D, X[ 1], 3 ); |
P( D, A, B, C, X[ 5], 5 ); |
P( C, D, A, B, X[ 9], 9 ); |
P( B, C, D, A, X[13], 13 ); |
P( A, B, C, D, X[ 2], 3 ); |
P( D, A, B, C, X[ 6], 5 ); |
P( C, D, A, B, X[10], 9 ); |
P( B, C, D, A, X[14], 13 ); |
P( A, B, C, D, X[ 3], 3 ); |
P( D, A, B, C, X[ 7], 5 ); |
P( C, D, A, B, X[11], 9 ); |
P( B, C, D, A, X[15], 13 ); |
#undef P |
#undef F |
#define F(x,y,z) ((x) ^ (y) ^ (z)) |
#define P(a,b,c,d,x,s) \ |
do \ |
{ \ |
(a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \ |
(a) = S((a),(s)); \ |
} while( 0 ) |
P( A, B, C, D, X[ 0], 3 ); |
P( D, A, B, C, X[ 8], 9 ); |
P( C, D, A, B, X[ 4], 11 ); |
P( B, C, D, A, X[12], 15 ); |
P( A, B, C, D, X[ 2], 3 ); |
P( D, A, B, C, X[10], 9 ); |
P( C, D, A, B, X[ 6], 11 ); |
P( B, C, D, A, X[14], 15 ); |
P( A, B, C, D, X[ 1], 3 ); |
P( D, A, B, C, X[ 9], 9 ); |
P( C, D, A, B, X[ 5], 11 ); |
P( B, C, D, A, X[13], 15 ); |
P( A, B, C, D, X[ 3], 3 ); |
P( D, A, B, C, X[11], 9 ); |
P( C, D, A, B, X[ 7], 11 ); |
P( B, C, D, A, X[15], 15 ); |
#undef F |
#undef P |
ctx->state[0] += A; |
ctx->state[1] += B; |
ctx->state[2] += C; |
ctx->state[3] += D; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md4_process( mbedtls_md4_context *ctx, |
const unsigned char data[64] ) |
{ |
mbedtls_internal_md4_process( ctx, data ); |
} |
#endif |
#endif /* !MBEDTLS_MD4_PROCESS_ALT */ |
/* |
* MD4 process buffer |
*/ |
int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
int ret; |
size_t fill; |
uint32_t left; |
if( ilen == 0 ) |
return( 0 ); |
left = ctx->total[0] & 0x3F; |
fill = 64 - left; |
ctx->total[0] += (uint32_t) ilen; |
ctx->total[0] &= 0xFFFFFFFF; |
if( ctx->total[0] < (uint32_t) ilen ) |
ctx->total[1]++; |
if( left && ilen >= fill ) |
{ |
memcpy( (void *) (ctx->buffer + left), |
(void *) input, fill ); |
if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
input += fill; |
ilen -= fill; |
left = 0; |
} |
while( ilen >= 64 ) |
{ |
if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) |
return( ret ); |
input += 64; |
ilen -= 64; |
} |
if( ilen > 0 ) |
{ |
memcpy( (void *) (ctx->buffer + left), |
(void *) input, ilen ); |
} |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md4_update( mbedtls_md4_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
mbedtls_md4_update_ret( ctx, input, ilen ); |
} |
#endif |
static const unsigned char md4_padding[64] = |
{ |
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
}; |
/* |
* MD4 final digest |
*/ |
int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, |
unsigned char output[16] ) |
{ |
int ret; |
uint32_t last, padn; |
uint32_t high, low; |
unsigned char msglen[8]; |
high = ( ctx->total[0] >> 29 ) |
| ( ctx->total[1] << 3 ); |
low = ( ctx->total[0] << 3 ); |
PUT_UINT32_LE( low, msglen, 0 ); |
PUT_UINT32_LE( high, msglen, 4 ); |
last = ctx->total[0] & 0x3F; |
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); |
ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); |
if( ret != 0 ) |
return( ret ); |
if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) |
return( ret ); |
PUT_UINT32_LE( ctx->state[0], output, 0 ); |
PUT_UINT32_LE( ctx->state[1], output, 4 ); |
PUT_UINT32_LE( ctx->state[2], output, 8 ); |
PUT_UINT32_LE( ctx->state[3], output, 12 ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md4_finish( mbedtls_md4_context *ctx, |
unsigned char output[16] ) |
{ |
mbedtls_md4_finish_ret( ctx, output ); |
} |
#endif |
#endif /* !MBEDTLS_MD4_ALT */ |
/* |
* output = MD4( input buffer ) |
*/ |
int mbedtls_md4_ret( const unsigned char *input, |
size_t ilen, |
unsigned char output[16] ) |
{ |
int ret; |
mbedtls_md4_context ctx; |
mbedtls_md4_init( &ctx ); |
if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_md4_free( &ctx ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md4( const unsigned char *input, |
size_t ilen, |
unsigned char output[16] ) |
{ |
mbedtls_md4_ret( input, ilen, output ); |
} |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* RFC 1320 test vectors |
*/ |
static const unsigned char md4_test_str[7][81] = |
{ |
{ "" }, |
{ "a" }, |
{ "abc" }, |
{ "message digest" }, |
{ "abcdefghijklmnopqrstuvwxyz" }, |
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, |
{ "12345678901234567890123456789012345678901234567890123456789012" |
"345678901234567890" } |
}; |
static const size_t md4_test_strlen[7] = |
{ |
0, 1, 3, 14, 26, 62, 80 |
}; |
static const unsigned char md4_test_sum[7][16] = |
{ |
{ 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, |
0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, |
{ 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, |
0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, |
{ 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, |
0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, |
{ 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, |
0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, |
{ 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, |
0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, |
{ 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, |
0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, |
{ 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, |
0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_md4_self_test( int verbose ) |
{ |
int i, ret = 0; |
unsigned char md4sum[16]; |
for( i = 0; i < 7; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " MD4 test #%d: ", i + 1 ); |
ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); |
if( ret != 0 ) |
goto fail; |
if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) |
{ |
ret = 1; |
goto fail; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
fail: |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_MD4_C */ |
/programs/develop/libraries/kos_mbedtls/library/md5.c |
---|
0,0 → 1,500 |
/* |
* RFC 1321 compliant MD5 implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The MD5 algorithm was designed by Ron Rivest in 1991. |
* |
* http://www.ietf.org/rfc/rfc1321.txt |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_MD5_C) |
#include "mbedtls/md5.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_MD5_ALT) |
/* |
* 32-bit integer manipulation macros (little endian) |
*/ |
#ifndef GET_UINT32_LE |
#define GET_UINT32_LE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] ) \ |
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 3] << 24 ); \ |
} |
#endif |
#ifndef PUT_UINT32_LE |
#define PUT_UINT32_LE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ |
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ |
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ |
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ |
} |
#endif |
void mbedtls_md5_init( mbedtls_md5_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_md5_context ) ); |
} |
void mbedtls_md5_free( mbedtls_md5_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); |
} |
void mbedtls_md5_clone( mbedtls_md5_context *dst, |
const mbedtls_md5_context *src ) |
{ |
*dst = *src; |
} |
/* |
* MD5 context setup |
*/ |
int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) |
{ |
ctx->total[0] = 0; |
ctx->total[1] = 0; |
ctx->state[0] = 0x67452301; |
ctx->state[1] = 0xEFCDAB89; |
ctx->state[2] = 0x98BADCFE; |
ctx->state[3] = 0x10325476; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md5_starts( mbedtls_md5_context *ctx ) |
{ |
mbedtls_md5_starts_ret( ctx ); |
} |
#endif |
#if !defined(MBEDTLS_MD5_PROCESS_ALT) |
int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, |
const unsigned char data[64] ) |
{ |
uint32_t X[16], A, B, C, D; |
GET_UINT32_LE( X[ 0], data, 0 ); |
GET_UINT32_LE( X[ 1], data, 4 ); |
GET_UINT32_LE( X[ 2], data, 8 ); |
GET_UINT32_LE( X[ 3], data, 12 ); |
GET_UINT32_LE( X[ 4], data, 16 ); |
GET_UINT32_LE( X[ 5], data, 20 ); |
GET_UINT32_LE( X[ 6], data, 24 ); |
GET_UINT32_LE( X[ 7], data, 28 ); |
GET_UINT32_LE( X[ 8], data, 32 ); |
GET_UINT32_LE( X[ 9], data, 36 ); |
GET_UINT32_LE( X[10], data, 40 ); |
GET_UINT32_LE( X[11], data, 44 ); |
GET_UINT32_LE( X[12], data, 48 ); |
GET_UINT32_LE( X[13], data, 52 ); |
GET_UINT32_LE( X[14], data, 56 ); |
GET_UINT32_LE( X[15], data, 60 ); |
#define S(x,n) \ |
( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) ) |
#define P(a,b,c,d,k,s,t) \ |
do \ |
{ \ |
(a) += F((b),(c),(d)) + X[(k)] + (t); \ |
(a) = S((a),(s)) + (b); \ |
} while( 0 ) |
A = ctx->state[0]; |
B = ctx->state[1]; |
C = ctx->state[2]; |
D = ctx->state[3]; |
#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) |
P( A, B, C, D, 0, 7, 0xD76AA478 ); |
P( D, A, B, C, 1, 12, 0xE8C7B756 ); |
P( C, D, A, B, 2, 17, 0x242070DB ); |
P( B, C, D, A, 3, 22, 0xC1BDCEEE ); |
P( A, B, C, D, 4, 7, 0xF57C0FAF ); |
P( D, A, B, C, 5, 12, 0x4787C62A ); |
P( C, D, A, B, 6, 17, 0xA8304613 ); |
P( B, C, D, A, 7, 22, 0xFD469501 ); |
P( A, B, C, D, 8, 7, 0x698098D8 ); |
P( D, A, B, C, 9, 12, 0x8B44F7AF ); |
P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); |
P( B, C, D, A, 11, 22, 0x895CD7BE ); |
P( A, B, C, D, 12, 7, 0x6B901122 ); |
P( D, A, B, C, 13, 12, 0xFD987193 ); |
P( C, D, A, B, 14, 17, 0xA679438E ); |
P( B, C, D, A, 15, 22, 0x49B40821 ); |
#undef F |
#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y)))) |
P( A, B, C, D, 1, 5, 0xF61E2562 ); |
P( D, A, B, C, 6, 9, 0xC040B340 ); |
P( C, D, A, B, 11, 14, 0x265E5A51 ); |
P( B, C, D, A, 0, 20, 0xE9B6C7AA ); |
P( A, B, C, D, 5, 5, 0xD62F105D ); |
P( D, A, B, C, 10, 9, 0x02441453 ); |
P( C, D, A, B, 15, 14, 0xD8A1E681 ); |
P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); |
P( A, B, C, D, 9, 5, 0x21E1CDE6 ); |
P( D, A, B, C, 14, 9, 0xC33707D6 ); |
P( C, D, A, B, 3, 14, 0xF4D50D87 ); |
P( B, C, D, A, 8, 20, 0x455A14ED ); |
P( A, B, C, D, 13, 5, 0xA9E3E905 ); |
P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); |
P( C, D, A, B, 7, 14, 0x676F02D9 ); |
P( B, C, D, A, 12, 20, 0x8D2A4C8A ); |
#undef F |
#define F(x,y,z) ((x) ^ (y) ^ (z)) |
P( A, B, C, D, 5, 4, 0xFFFA3942 ); |
P( D, A, B, C, 8, 11, 0x8771F681 ); |
P( C, D, A, B, 11, 16, 0x6D9D6122 ); |
P( B, C, D, A, 14, 23, 0xFDE5380C ); |
P( A, B, C, D, 1, 4, 0xA4BEEA44 ); |
P( D, A, B, C, 4, 11, 0x4BDECFA9 ); |
P( C, D, A, B, 7, 16, 0xF6BB4B60 ); |
P( B, C, D, A, 10, 23, 0xBEBFBC70 ); |
P( A, B, C, D, 13, 4, 0x289B7EC6 ); |
P( D, A, B, C, 0, 11, 0xEAA127FA ); |
P( C, D, A, B, 3, 16, 0xD4EF3085 ); |
P( B, C, D, A, 6, 23, 0x04881D05 ); |
P( A, B, C, D, 9, 4, 0xD9D4D039 ); |
P( D, A, B, C, 12, 11, 0xE6DB99E5 ); |
P( C, D, A, B, 15, 16, 0x1FA27CF8 ); |
P( B, C, D, A, 2, 23, 0xC4AC5665 ); |
#undef F |
#define F(x,y,z) ((y) ^ ((x) | ~(z))) |
P( A, B, C, D, 0, 6, 0xF4292244 ); |
P( D, A, B, C, 7, 10, 0x432AFF97 ); |
P( C, D, A, B, 14, 15, 0xAB9423A7 ); |
P( B, C, D, A, 5, 21, 0xFC93A039 ); |
P( A, B, C, D, 12, 6, 0x655B59C3 ); |
P( D, A, B, C, 3, 10, 0x8F0CCC92 ); |
P( C, D, A, B, 10, 15, 0xFFEFF47D ); |
P( B, C, D, A, 1, 21, 0x85845DD1 ); |
P( A, B, C, D, 8, 6, 0x6FA87E4F ); |
P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); |
P( C, D, A, B, 6, 15, 0xA3014314 ); |
P( B, C, D, A, 13, 21, 0x4E0811A1 ); |
P( A, B, C, D, 4, 6, 0xF7537E82 ); |
P( D, A, B, C, 11, 10, 0xBD3AF235 ); |
P( C, D, A, B, 2, 15, 0x2AD7D2BB ); |
P( B, C, D, A, 9, 21, 0xEB86D391 ); |
#undef F |
ctx->state[0] += A; |
ctx->state[1] += B; |
ctx->state[2] += C; |
ctx->state[3] += D; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md5_process( mbedtls_md5_context *ctx, |
const unsigned char data[64] ) |
{ |
mbedtls_internal_md5_process( ctx, data ); |
} |
#endif |
#endif /* !MBEDTLS_MD5_PROCESS_ALT */ |
/* |
* MD5 process buffer |
*/ |
int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
int ret; |
size_t fill; |
uint32_t left; |
if( ilen == 0 ) |
return( 0 ); |
left = ctx->total[0] & 0x3F; |
fill = 64 - left; |
ctx->total[0] += (uint32_t) ilen; |
ctx->total[0] &= 0xFFFFFFFF; |
if( ctx->total[0] < (uint32_t) ilen ) |
ctx->total[1]++; |
if( left && ilen >= fill ) |
{ |
memcpy( (void *) (ctx->buffer + left), input, fill ); |
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
input += fill; |
ilen -= fill; |
left = 0; |
} |
while( ilen >= 64 ) |
{ |
if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) |
return( ret ); |
input += 64; |
ilen -= 64; |
} |
if( ilen > 0 ) |
{ |
memcpy( (void *) (ctx->buffer + left), input, ilen ); |
} |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md5_update( mbedtls_md5_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
mbedtls_md5_update_ret( ctx, input, ilen ); |
} |
#endif |
/* |
* MD5 final digest |
*/ |
int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, |
unsigned char output[16] ) |
{ |
int ret; |
uint32_t used; |
uint32_t high, low; |
/* |
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length |
*/ |
used = ctx->total[0] & 0x3F; |
ctx->buffer[used++] = 0x80; |
if( used <= 56 ) |
{ |
/* Enough room for padding + length in current block */ |
memset( ctx->buffer + used, 0, 56 - used ); |
} |
else |
{ |
/* We'll need an extra block */ |
memset( ctx->buffer + used, 0, 64 - used ); |
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
memset( ctx->buffer, 0, 56 ); |
} |
/* |
* Add message length |
*/ |
high = ( ctx->total[0] >> 29 ) |
| ( ctx->total[1] << 3 ); |
low = ( ctx->total[0] << 3 ); |
PUT_UINT32_LE( low, ctx->buffer, 56 ); |
PUT_UINT32_LE( high, ctx->buffer, 60 ); |
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
/* |
* Output final state |
*/ |
PUT_UINT32_LE( ctx->state[0], output, 0 ); |
PUT_UINT32_LE( ctx->state[1], output, 4 ); |
PUT_UINT32_LE( ctx->state[2], output, 8 ); |
PUT_UINT32_LE( ctx->state[3], output, 12 ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md5_finish( mbedtls_md5_context *ctx, |
unsigned char output[16] ) |
{ |
mbedtls_md5_finish_ret( ctx, output ); |
} |
#endif |
#endif /* !MBEDTLS_MD5_ALT */ |
/* |
* output = MD5( input buffer ) |
*/ |
int mbedtls_md5_ret( const unsigned char *input, |
size_t ilen, |
unsigned char output[16] ) |
{ |
int ret; |
mbedtls_md5_context ctx; |
mbedtls_md5_init( &ctx ); |
if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_md5_free( &ctx ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_md5( const unsigned char *input, |
size_t ilen, |
unsigned char output[16] ) |
{ |
mbedtls_md5_ret( input, ilen, output ); |
} |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* RFC 1321 test vectors |
*/ |
static const unsigned char md5_test_buf[7][81] = |
{ |
{ "" }, |
{ "a" }, |
{ "abc" }, |
{ "message digest" }, |
{ "abcdefghijklmnopqrstuvwxyz" }, |
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, |
{ "12345678901234567890123456789012345678901234567890123456789012" |
"345678901234567890" } |
}; |
static const size_t md5_test_buflen[7] = |
{ |
0, 1, 3, 14, 26, 62, 80 |
}; |
static const unsigned char md5_test_sum[7][16] = |
{ |
{ 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, |
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, |
{ 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, |
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, |
{ 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, |
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, |
{ 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, |
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, |
{ 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, |
0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, |
{ 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, |
0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, |
{ 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, |
0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_md5_self_test( int verbose ) |
{ |
int i, ret = 0; |
unsigned char md5sum[16]; |
for( i = 0; i < 7; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " MD5 test #%d: ", i + 1 ); |
ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); |
if( ret != 0 ) |
goto fail; |
if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) |
{ |
ret = 1; |
goto fail; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
fail: |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_MD5_C */ |
/programs/develop/libraries/kos_mbedtls/library/md_wrap.c |
---|
0,0 → 1,588 |
/** |
* \file md_wrap.c |
* |
* \brief Generic message digest wrapper for mbed TLS |
* |
* \author Adriaan de Jong <dejong@fox-it.com> |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_MD_C) |
#include "mbedtls/md_internal.h" |
#if defined(MBEDTLS_MD2_C) |
#include "mbedtls/md2.h" |
#endif |
#if defined(MBEDTLS_MD4_C) |
#include "mbedtls/md4.h" |
#endif |
#if defined(MBEDTLS_MD5_C) |
#include "mbedtls/md5.h" |
#endif |
#if defined(MBEDTLS_RIPEMD160_C) |
#include "mbedtls/ripemd160.h" |
#endif |
#if defined(MBEDTLS_SHA1_C) |
#include "mbedtls/sha1.h" |
#endif |
#if defined(MBEDTLS_SHA256_C) |
#include "mbedtls/sha256.h" |
#endif |
#if defined(MBEDTLS_SHA512_C) |
#include "mbedtls/sha512.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#if defined(MBEDTLS_MD2_C) |
static int md2_starts_wrap( void *ctx ) |
{ |
return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) ); |
} |
static int md2_update_wrap( void *ctx, const unsigned char *input, |
size_t ilen ) |
{ |
return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) ); |
} |
static int md2_finish_wrap( void *ctx, unsigned char *output ) |
{ |
return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) ); |
} |
static void *md2_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); |
if( ctx != NULL ) |
mbedtls_md2_init( (mbedtls_md2_context *) ctx ); |
return( ctx ); |
} |
static void md2_ctx_free( void *ctx ) |
{ |
mbedtls_md2_free( (mbedtls_md2_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void md2_clone_wrap( void *dst, const void *src ) |
{ |
mbedtls_md2_clone( (mbedtls_md2_context *) dst, |
(const mbedtls_md2_context *) src ); |
} |
static int md2_process_wrap( void *ctx, const unsigned char *data ) |
{ |
((void) data); |
return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) ); |
} |
const mbedtls_md_info_t mbedtls_md2_info = { |
MBEDTLS_MD_MD2, |
"MD2", |
16, |
16, |
md2_starts_wrap, |
md2_update_wrap, |
md2_finish_wrap, |
mbedtls_md2_ret, |
md2_ctx_alloc, |
md2_ctx_free, |
md2_clone_wrap, |
md2_process_wrap, |
}; |
#endif /* MBEDTLS_MD2_C */ |
#if defined(MBEDTLS_MD4_C) |
static int md4_starts_wrap( void *ctx ) |
{ |
return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) ); |
} |
static int md4_update_wrap( void *ctx, const unsigned char *input, |
size_t ilen ) |
{ |
return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) ); |
} |
static int md4_finish_wrap( void *ctx, unsigned char *output ) |
{ |
return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) ); |
} |
static void *md4_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); |
if( ctx != NULL ) |
mbedtls_md4_init( (mbedtls_md4_context *) ctx ); |
return( ctx ); |
} |
static void md4_ctx_free( void *ctx ) |
{ |
mbedtls_md4_free( (mbedtls_md4_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void md4_clone_wrap( void *dst, const void *src ) |
{ |
mbedtls_md4_clone( (mbedtls_md4_context *) dst, |
(const mbedtls_md4_context *) src ); |
} |
static int md4_process_wrap( void *ctx, const unsigned char *data ) |
{ |
return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) ); |
} |
const mbedtls_md_info_t mbedtls_md4_info = { |
MBEDTLS_MD_MD4, |
"MD4", |
16, |
64, |
md4_starts_wrap, |
md4_update_wrap, |
md4_finish_wrap, |
mbedtls_md4_ret, |
md4_ctx_alloc, |
md4_ctx_free, |
md4_clone_wrap, |
md4_process_wrap, |
}; |
#endif /* MBEDTLS_MD4_C */ |
#if defined(MBEDTLS_MD5_C) |
static int md5_starts_wrap( void *ctx ) |
{ |
return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) ); |
} |
static int md5_update_wrap( void *ctx, const unsigned char *input, |
size_t ilen ) |
{ |
return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) ); |
} |
static int md5_finish_wrap( void *ctx, unsigned char *output ) |
{ |
return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) ); |
} |
static void *md5_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); |
if( ctx != NULL ) |
mbedtls_md5_init( (mbedtls_md5_context *) ctx ); |
return( ctx ); |
} |
static void md5_ctx_free( void *ctx ) |
{ |
mbedtls_md5_free( (mbedtls_md5_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void md5_clone_wrap( void *dst, const void *src ) |
{ |
mbedtls_md5_clone( (mbedtls_md5_context *) dst, |
(const mbedtls_md5_context *) src ); |
} |
static int md5_process_wrap( void *ctx, const unsigned char *data ) |
{ |
return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) ); |
} |
const mbedtls_md_info_t mbedtls_md5_info = { |
MBEDTLS_MD_MD5, |
"MD5", |
16, |
64, |
md5_starts_wrap, |
md5_update_wrap, |
md5_finish_wrap, |
mbedtls_md5_ret, |
md5_ctx_alloc, |
md5_ctx_free, |
md5_clone_wrap, |
md5_process_wrap, |
}; |
#endif /* MBEDTLS_MD5_C */ |
#if defined(MBEDTLS_RIPEMD160_C) |
static int ripemd160_starts_wrap( void *ctx ) |
{ |
return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) ); |
} |
static int ripemd160_update_wrap( void *ctx, const unsigned char *input, |
size_t ilen ) |
{ |
return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx, |
input, ilen ) ); |
} |
static int ripemd160_finish_wrap( void *ctx, unsigned char *output ) |
{ |
return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx, |
output ) ); |
} |
static void *ripemd160_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); |
if( ctx != NULL ) |
mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); |
return( ctx ); |
} |
static void ripemd160_ctx_free( void *ctx ) |
{ |
mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void ripemd160_clone_wrap( void *dst, const void *src ) |
{ |
mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, |
(const mbedtls_ripemd160_context *) src ); |
} |
static int ripemd160_process_wrap( void *ctx, const unsigned char *data ) |
{ |
return( mbedtls_internal_ripemd160_process( |
(mbedtls_ripemd160_context *) ctx, data ) ); |
} |
const mbedtls_md_info_t mbedtls_ripemd160_info = { |
MBEDTLS_MD_RIPEMD160, |
"RIPEMD160", |
20, |
64, |
ripemd160_starts_wrap, |
ripemd160_update_wrap, |
ripemd160_finish_wrap, |
mbedtls_ripemd160_ret, |
ripemd160_ctx_alloc, |
ripemd160_ctx_free, |
ripemd160_clone_wrap, |
ripemd160_process_wrap, |
}; |
#endif /* MBEDTLS_RIPEMD160_C */ |
#if defined(MBEDTLS_SHA1_C) |
static int sha1_starts_wrap( void *ctx ) |
{ |
return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) ); |
} |
static int sha1_update_wrap( void *ctx, const unsigned char *input, |
size_t ilen ) |
{ |
return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx, |
input, ilen ) ); |
} |
static int sha1_finish_wrap( void *ctx, unsigned char *output ) |
{ |
return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) ); |
} |
static void *sha1_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); |
if( ctx != NULL ) |
mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); |
return( ctx ); |
} |
static void sha1_clone_wrap( void *dst, const void *src ) |
{ |
mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, |
(const mbedtls_sha1_context *) src ); |
} |
static void sha1_ctx_free( void *ctx ) |
{ |
mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static int sha1_process_wrap( void *ctx, const unsigned char *data ) |
{ |
return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx, |
data ) ); |
} |
const mbedtls_md_info_t mbedtls_sha1_info = { |
MBEDTLS_MD_SHA1, |
"SHA1", |
20, |
64, |
sha1_starts_wrap, |
sha1_update_wrap, |
sha1_finish_wrap, |
mbedtls_sha1_ret, |
sha1_ctx_alloc, |
sha1_ctx_free, |
sha1_clone_wrap, |
sha1_process_wrap, |
}; |
#endif /* MBEDTLS_SHA1_C */ |
/* |
* Wrappers for generic message digests |
*/ |
#if defined(MBEDTLS_SHA256_C) |
static int sha224_starts_wrap( void *ctx ) |
{ |
return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) ); |
} |
static int sha224_update_wrap( void *ctx, const unsigned char *input, |
size_t ilen ) |
{ |
return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx, |
input, ilen ) ); |
} |
static int sha224_finish_wrap( void *ctx, unsigned char *output ) |
{ |
return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx, |
output ) ); |
} |
static int sha224_wrap( const unsigned char *input, size_t ilen, |
unsigned char *output ) |
{ |
return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); |
} |
static void *sha224_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); |
if( ctx != NULL ) |
mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); |
return( ctx ); |
} |
static void sha224_ctx_free( void *ctx ) |
{ |
mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void sha224_clone_wrap( void *dst, const void *src ) |
{ |
mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, |
(const mbedtls_sha256_context *) src ); |
} |
static int sha224_process_wrap( void *ctx, const unsigned char *data ) |
{ |
return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx, |
data ) ); |
} |
const mbedtls_md_info_t mbedtls_sha224_info = { |
MBEDTLS_MD_SHA224, |
"SHA224", |
28, |
64, |
sha224_starts_wrap, |
sha224_update_wrap, |
sha224_finish_wrap, |
sha224_wrap, |
sha224_ctx_alloc, |
sha224_ctx_free, |
sha224_clone_wrap, |
sha224_process_wrap, |
}; |
static int sha256_starts_wrap( void *ctx ) |
{ |
return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) ); |
} |
static int sha256_wrap( const unsigned char *input, size_t ilen, |
unsigned char *output ) |
{ |
return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); |
} |
const mbedtls_md_info_t mbedtls_sha256_info = { |
MBEDTLS_MD_SHA256, |
"SHA256", |
32, |
64, |
sha256_starts_wrap, |
sha224_update_wrap, |
sha224_finish_wrap, |
sha256_wrap, |
sha224_ctx_alloc, |
sha224_ctx_free, |
sha224_clone_wrap, |
sha224_process_wrap, |
}; |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
static int sha384_starts_wrap( void *ctx ) |
{ |
return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) ); |
} |
static int sha384_update_wrap( void *ctx, const unsigned char *input, |
size_t ilen ) |
{ |
return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx, |
input, ilen ) ); |
} |
static int sha384_finish_wrap( void *ctx, unsigned char *output ) |
{ |
return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx, |
output ) ); |
} |
static int sha384_wrap( const unsigned char *input, size_t ilen, |
unsigned char *output ) |
{ |
return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); |
} |
static void *sha384_ctx_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); |
if( ctx != NULL ) |
mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); |
return( ctx ); |
} |
static void sha384_ctx_free( void *ctx ) |
{ |
mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void sha384_clone_wrap( void *dst, const void *src ) |
{ |
mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, |
(const mbedtls_sha512_context *) src ); |
} |
static int sha384_process_wrap( void *ctx, const unsigned char *data ) |
{ |
return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx, |
data ) ); |
} |
const mbedtls_md_info_t mbedtls_sha384_info = { |
MBEDTLS_MD_SHA384, |
"SHA384", |
48, |
128, |
sha384_starts_wrap, |
sha384_update_wrap, |
sha384_finish_wrap, |
sha384_wrap, |
sha384_ctx_alloc, |
sha384_ctx_free, |
sha384_clone_wrap, |
sha384_process_wrap, |
}; |
static int sha512_starts_wrap( void *ctx ) |
{ |
return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) ); |
} |
static int sha512_wrap( const unsigned char *input, size_t ilen, |
unsigned char *output ) |
{ |
return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); |
} |
const mbedtls_md_info_t mbedtls_sha512_info = { |
MBEDTLS_MD_SHA512, |
"SHA512", |
64, |
128, |
sha512_starts_wrap, |
sha384_update_wrap, |
sha384_finish_wrap, |
sha512_wrap, |
sha384_ctx_alloc, |
sha384_ctx_free, |
sha384_clone_wrap, |
sha384_process_wrap, |
}; |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_MD_C */ |
/programs/develop/libraries/kos_mbedtls/library/memory_buffer_alloc.c |
---|
0,0 → 1,752 |
/* |
* Buffer-based memory allocator |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) |
#include "mbedtls/memory_buffer_alloc.h" |
/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C |
is dependent upon MBEDTLS_PLATFORM_C */ |
#include "mbedtls/platform.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
#include <execinfo.h> |
#endif |
#if defined(MBEDTLS_THREADING_C) |
#include "mbedtls/threading.h" |
#endif |
#define MAGIC1 0xFF00AA55 |
#define MAGIC2 0xEE119966 |
#define MAX_BT 20 |
typedef struct _memory_header memory_header; |
struct _memory_header |
{ |
size_t magic1; |
size_t size; |
size_t alloc; |
memory_header *prev; |
memory_header *next; |
memory_header *prev_free; |
memory_header *next_free; |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
char **trace; |
size_t trace_count; |
#endif |
size_t magic2; |
}; |
typedef struct |
{ |
unsigned char *buf; |
size_t len; |
memory_header *first; |
memory_header *first_free; |
int verify; |
#if defined(MBEDTLS_MEMORY_DEBUG) |
size_t alloc_count; |
size_t free_count; |
size_t total_used; |
size_t maximum_used; |
size_t header_count; |
size_t maximum_header_count; |
#endif |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_threading_mutex_t mutex; |
#endif |
} |
buffer_alloc_ctx; |
static buffer_alloc_ctx heap; |
#if defined(MBEDTLS_MEMORY_DEBUG) |
static void debug_header( memory_header *hdr ) |
{ |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
size_t i; |
#endif |
mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " |
"ALLOC(%zu), SIZE(%10zu)\n", |
(size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, |
hdr->alloc, hdr->size ); |
mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", |
(size_t) hdr->prev_free, (size_t) hdr->next_free ); |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
mbedtls_fprintf( stderr, "TRACE: \n" ); |
for( i = 0; i < hdr->trace_count; i++ ) |
mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); |
mbedtls_fprintf( stderr, "\n" ); |
#endif |
} |
static void debug_chain( void ) |
{ |
memory_header *cur = heap.first; |
mbedtls_fprintf( stderr, "\nBlock list\n" ); |
while( cur != NULL ) |
{ |
debug_header( cur ); |
cur = cur->next; |
} |
mbedtls_fprintf( stderr, "Free list\n" ); |
cur = heap.first_free; |
while( cur != NULL ) |
{ |
debug_header( cur ); |
cur = cur->next_free; |
} |
} |
#endif /* MBEDTLS_MEMORY_DEBUG */ |
static int verify_header( memory_header *hdr ) |
{ |
if( hdr->magic1 != MAGIC1 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); |
#endif |
return( 1 ); |
} |
if( hdr->magic2 != MAGIC2 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); |
#endif |
return( 1 ); |
} |
if( hdr->alloc > 1 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); |
#endif |
return( 1 ); |
} |
if( hdr->prev != NULL && hdr->prev == hdr->next ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); |
#endif |
return( 1 ); |
} |
if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); |
#endif |
return( 1 ); |
} |
return( 0 ); |
} |
static int verify_chain( void ) |
{ |
memory_header *prv = heap.first, *cur; |
if( prv == NULL || verify_header( prv ) != 0 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: verification of first header " |
"failed\n" ); |
#endif |
return( 1 ); |
} |
if( heap.first->prev != NULL ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: verification failed: " |
"first->prev != NULL\n" ); |
#endif |
return( 1 ); |
} |
cur = heap.first->next; |
while( cur != NULL ) |
{ |
if( verify_header( cur ) != 0 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: verification of header " |
"failed\n" ); |
#endif |
return( 1 ); |
} |
if( cur->prev != prv ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: verification failed: " |
"cur->prev != prv\n" ); |
#endif |
return( 1 ); |
} |
prv = cur; |
cur = cur->next; |
} |
return( 0 ); |
} |
static void *buffer_alloc_calloc( size_t n, size_t size ) |
{ |
memory_header *new, *cur = heap.first_free; |
unsigned char *p; |
void *ret; |
size_t original_len, len; |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
void *trace_buffer[MAX_BT]; |
size_t trace_cnt; |
#endif |
if( heap.buf == NULL || heap.first == NULL ) |
return( NULL ); |
original_len = len = n * size; |
if( n == 0 || size == 0 || len / n != size ) |
return( NULL ); |
else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) |
return( NULL ); |
if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) |
{ |
len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; |
len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; |
} |
// Find block that fits |
// |
while( cur != NULL ) |
{ |
if( cur->size >= len ) |
break; |
cur = cur->next_free; |
} |
if( cur == NULL ) |
return( NULL ); |
if( cur->alloc != 0 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " |
"data\n" ); |
#endif |
mbedtls_exit( 1 ); |
} |
#if defined(MBEDTLS_MEMORY_DEBUG) |
heap.alloc_count++; |
#endif |
// Found location, split block if > memory_header + 4 room left |
// |
if( cur->size - len < sizeof(memory_header) + |
MBEDTLS_MEMORY_ALIGN_MULTIPLE ) |
{ |
cur->alloc = 1; |
// Remove from free_list |
// |
if( cur->prev_free != NULL ) |
cur->prev_free->next_free = cur->next_free; |
else |
heap.first_free = cur->next_free; |
if( cur->next_free != NULL ) |
cur->next_free->prev_free = cur->prev_free; |
cur->prev_free = NULL; |
cur->next_free = NULL; |
#if defined(MBEDTLS_MEMORY_DEBUG) |
heap.total_used += cur->size; |
if( heap.total_used > heap.maximum_used ) |
heap.maximum_used = heap.total_used; |
#endif |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
trace_cnt = backtrace( trace_buffer, MAX_BT ); |
cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); |
cur->trace_count = trace_cnt; |
#endif |
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) |
mbedtls_exit( 1 ); |
ret = (unsigned char *) cur + sizeof( memory_header ); |
memset( ret, 0, original_len ); |
return( ret ); |
} |
p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; |
new = (memory_header *) p; |
new->size = cur->size - len - sizeof(memory_header); |
new->alloc = 0; |
new->prev = cur; |
new->next = cur->next; |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
new->trace = NULL; |
new->trace_count = 0; |
#endif |
new->magic1 = MAGIC1; |
new->magic2 = MAGIC2; |
if( new->next != NULL ) |
new->next->prev = new; |
// Replace cur with new in free_list |
// |
new->prev_free = cur->prev_free; |
new->next_free = cur->next_free; |
if( new->prev_free != NULL ) |
new->prev_free->next_free = new; |
else |
heap.first_free = new; |
if( new->next_free != NULL ) |
new->next_free->prev_free = new; |
cur->alloc = 1; |
cur->size = len; |
cur->next = new; |
cur->prev_free = NULL; |
cur->next_free = NULL; |
#if defined(MBEDTLS_MEMORY_DEBUG) |
heap.header_count++; |
if( heap.header_count > heap.maximum_header_count ) |
heap.maximum_header_count = heap.header_count; |
heap.total_used += cur->size; |
if( heap.total_used > heap.maximum_used ) |
heap.maximum_used = heap.total_used; |
#endif |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
trace_cnt = backtrace( trace_buffer, MAX_BT ); |
cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); |
cur->trace_count = trace_cnt; |
#endif |
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) |
mbedtls_exit( 1 ); |
ret = (unsigned char *) cur + sizeof( memory_header ); |
memset( ret, 0, original_len ); |
return( ret ); |
} |
static void buffer_alloc_free( void *ptr ) |
{ |
memory_header *hdr, *old = NULL; |
unsigned char *p = (unsigned char *) ptr; |
if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) |
return; |
if( p < heap.buf || p >= heap.buf + heap.len ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " |
"space\n" ); |
#endif |
mbedtls_exit( 1 ); |
} |
p -= sizeof(memory_header); |
hdr = (memory_header *) p; |
if( verify_header( hdr ) != 0 ) |
mbedtls_exit( 1 ); |
if( hdr->alloc != 1 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " |
"data\n" ); |
#endif |
mbedtls_exit( 1 ); |
} |
hdr->alloc = 0; |
#if defined(MBEDTLS_MEMORY_DEBUG) |
heap.free_count++; |
heap.total_used -= hdr->size; |
#endif |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
free( hdr->trace ); |
hdr->trace = NULL; |
hdr->trace_count = 0; |
#endif |
// Regroup with block before |
// |
if( hdr->prev != NULL && hdr->prev->alloc == 0 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
heap.header_count--; |
#endif |
hdr->prev->size += sizeof(memory_header) + hdr->size; |
hdr->prev->next = hdr->next; |
old = hdr; |
hdr = hdr->prev; |
if( hdr->next != NULL ) |
hdr->next->prev = hdr; |
memset( old, 0, sizeof(memory_header) ); |
} |
// Regroup with block after |
// |
if( hdr->next != NULL && hdr->next->alloc == 0 ) |
{ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
heap.header_count--; |
#endif |
hdr->size += sizeof(memory_header) + hdr->next->size; |
old = hdr->next; |
hdr->next = hdr->next->next; |
if( hdr->prev_free != NULL || hdr->next_free != NULL ) |
{ |
if( hdr->prev_free != NULL ) |
hdr->prev_free->next_free = hdr->next_free; |
else |
heap.first_free = hdr->next_free; |
if( hdr->next_free != NULL ) |
hdr->next_free->prev_free = hdr->prev_free; |
} |
hdr->prev_free = old->prev_free; |
hdr->next_free = old->next_free; |
if( hdr->prev_free != NULL ) |
hdr->prev_free->next_free = hdr; |
else |
heap.first_free = hdr; |
if( hdr->next_free != NULL ) |
hdr->next_free->prev_free = hdr; |
if( hdr->next != NULL ) |
hdr->next->prev = hdr; |
memset( old, 0, sizeof(memory_header) ); |
} |
// Prepend to free_list if we have not merged |
// (Does not have to stay in same order as prev / next list) |
// |
if( old == NULL ) |
{ |
hdr->next_free = heap.first_free; |
if( heap.first_free != NULL ) |
heap.first_free->prev_free = hdr; |
heap.first_free = hdr; |
} |
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) |
mbedtls_exit( 1 ); |
} |
void mbedtls_memory_buffer_set_verify( int verify ) |
{ |
heap.verify = verify; |
} |
int mbedtls_memory_buffer_alloc_verify( void ) |
{ |
return verify_chain(); |
} |
#if defined(MBEDTLS_MEMORY_DEBUG) |
void mbedtls_memory_buffer_alloc_status( void ) |
{ |
mbedtls_fprintf( stderr, |
"Current use: %zu blocks / %zu bytes, max: %zu blocks / " |
"%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", |
heap.header_count, heap.total_used, |
heap.maximum_header_count, heap.maximum_used, |
heap.maximum_header_count * sizeof( memory_header ) |
+ heap.maximum_used, |
heap.alloc_count, heap.free_count ); |
if( heap.first->next == NULL ) |
{ |
mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); |
} |
else |
{ |
mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); |
debug_chain(); |
} |
} |
void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) |
{ |
*max_used = heap.maximum_used; |
*max_blocks = heap.maximum_header_count; |
} |
void mbedtls_memory_buffer_alloc_max_reset( void ) |
{ |
heap.maximum_used = 0; |
heap.maximum_header_count = 0; |
} |
void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) |
{ |
*cur_used = heap.total_used; |
*cur_blocks = heap.header_count; |
} |
#endif /* MBEDTLS_MEMORY_DEBUG */ |
#if defined(MBEDTLS_THREADING_C) |
static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) |
{ |
void *buf; |
if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) |
return( NULL ); |
buf = buffer_alloc_calloc( n, size ); |
if( mbedtls_mutex_unlock( &heap.mutex ) ) |
return( NULL ); |
return( buf ); |
} |
static void buffer_alloc_free_mutexed( void *ptr ) |
{ |
/* We have to good option here, but corrupting the heap seems |
* worse than loosing memory. */ |
if( mbedtls_mutex_lock( &heap.mutex ) ) |
return; |
buffer_alloc_free( ptr ); |
(void) mbedtls_mutex_unlock( &heap.mutex ); |
} |
#endif /* MBEDTLS_THREADING_C */ |
void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) |
{ |
memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &heap.mutex ); |
mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, |
buffer_alloc_free_mutexed ); |
#else |
mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); |
#endif |
if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) |
return; |
else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) |
{ |
/* Adjust len first since buf is used in the computation */ |
len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE |
- (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; |
buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE |
- (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; |
} |
memset( buf, 0, len ); |
heap.buf = buf; |
heap.len = len; |
heap.first = (memory_header *)buf; |
heap.first->size = len - sizeof( memory_header ); |
heap.first->magic1 = MAGIC1; |
heap.first->magic2 = MAGIC2; |
heap.first_free = heap.first; |
} |
void mbedtls_memory_buffer_alloc_free( void ) |
{ |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &heap.mutex ); |
#endif |
mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); |
} |
#if defined(MBEDTLS_SELF_TEST) |
static int check_pointer( void *p ) |
{ |
if( p == NULL ) |
return( -1 ); |
if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) |
return( -1 ); |
return( 0 ); |
} |
static int check_all_free( void ) |
{ |
if( |
#if defined(MBEDTLS_MEMORY_DEBUG) |
heap.total_used != 0 || |
#endif |
heap.first != heap.first_free || |
(void *) heap.first != (void *) heap.buf ) |
{ |
return( -1 ); |
} |
return( 0 ); |
} |
#define TEST_ASSERT( condition ) \ |
if( ! (condition) ) \ |
{ \ |
if( verbose != 0 ) \ |
mbedtls_printf( "failed\n" ); \ |
\ |
ret = 1; \ |
goto cleanup; \ |
} |
int mbedtls_memory_buffer_alloc_self_test( int verbose ) |
{ |
unsigned char buf[1024]; |
unsigned char *p, *q, *r, *end; |
int ret = 0; |
if( verbose != 0 ) |
mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); |
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); |
p = mbedtls_calloc( 1, 1 ); |
q = mbedtls_calloc( 1, 128 ); |
r = mbedtls_calloc( 1, 16 ); |
TEST_ASSERT( check_pointer( p ) == 0 && |
check_pointer( q ) == 0 && |
check_pointer( r ) == 0 ); |
mbedtls_free( r ); |
mbedtls_free( q ); |
mbedtls_free( p ); |
TEST_ASSERT( check_all_free( ) == 0 ); |
/* Memorize end to compare with the next test */ |
end = heap.buf + heap.len; |
mbedtls_memory_buffer_alloc_free( ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " MBA test #2 (buf not aligned): " ); |
mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); |
TEST_ASSERT( heap.buf + heap.len == end ); |
p = mbedtls_calloc( 1, 1 ); |
q = mbedtls_calloc( 1, 128 ); |
r = mbedtls_calloc( 1, 16 ); |
TEST_ASSERT( check_pointer( p ) == 0 && |
check_pointer( q ) == 0 && |
check_pointer( r ) == 0 ); |
mbedtls_free( r ); |
mbedtls_free( q ); |
mbedtls_free( p ); |
TEST_ASSERT( check_all_free( ) == 0 ); |
mbedtls_memory_buffer_alloc_free( ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " MBA test #3 (full): " ); |
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); |
p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); |
TEST_ASSERT( check_pointer( p ) == 0 ); |
TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); |
mbedtls_free( p ); |
p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); |
q = mbedtls_calloc( 1, 16 ); |
TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); |
TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); |
mbedtls_free( q ); |
TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); |
mbedtls_free( p ); |
TEST_ASSERT( check_all_free( ) == 0 ); |
mbedtls_memory_buffer_alloc_free( ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
cleanup: |
mbedtls_memory_buffer_alloc_free( ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ |
/programs/develop/libraries/kos_mbedtls/library/net_sockets.c |
---|
0,0 → 1,213 |
/* |
* TCP/IP or UDP/IP networking functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must |
* be set before config.h, which pulls in glibc's features.h indirectly. |
* Harmless on other platforms. */ |
#define _POSIX_C_SOURCE 200112L |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_NET_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#endif |
#include "mbedtls/net_sockets.h" |
#include <string.h> |
#include "kosnet/socket.h" |
#include "kosnet/network.h" |
/*#include <sys/socket.h> |
#include <netinet/in.h> |
#include <arpa/inet.h> |
#include <sys/time.h> |
#include <unistd.h> |
#include <signal.h> |
#include <fcntl.h> |
#include <netdb.h> |
#include <errno.h> |
*/ |
#define IS_EINTR( ret ) ( ( ret ) == EINTR ) |
#include <stdio.h> |
//#include <time.h> |
#include <stdint.h> |
/* |
* Prepare for using the sockets interface |
*/ |
static int net_prepare( void ) |
{ |
load_network_obj(); |
return( 0 ); |
} |
/* |
* Initialize a context |
*/ |
void mbedtls_net_init( mbedtls_net_context *ctx ) |
{ |
ctx->fd = -1; |
} |
/* |
* Initiate a TCP connection with host:port and the given protocol |
*/ |
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, |
const char *port, int proto ) |
{ |
int ret; |
struct addrinfo hints, *addr_list, *cur; |
if( ( ret = net_prepare() ) != 0 ) |
return( ret ); |
/* Do name resolution with both IPv6 and IPv4 */ |
memset( &hints, 0, sizeof( hints ) ); |
hints.ai_family = AF_UNSPEC; |
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; |
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; |
if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) |
return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); |
/* Try the sockaddrs until a connection succeeds */ |
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; |
for( cur = addr_list; cur != NULL; cur = cur->ai_next ) |
{ |
ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, |
cur->ai_protocol ); |
if( ctx->fd < 0 ) |
{ |
ret = MBEDTLS_ERR_NET_SOCKET_FAILED; |
continue; |
} |
if( connect( ctx->fd, cur->ai_addr, (int) cur->ai_addrlen ) == 0 ) |
{ |
ret = 0; |
break; |
} |
closesocket( ctx->fd ); |
ret = MBEDTLS_ERR_NET_CONNECT_FAILED; |
} |
freeaddrinfo( addr_list ); |
return( ret ); |
} |
/**************************/ |
/* |
* Read at most 'len' characters |
*/ |
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) |
{ |
int ret; |
int fd = ((mbedtls_net_context *) ctx)->fd; |
if( fd < 0 ) |
return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); |
ret = (int) recv( fd, (char*)( buf ), (int)( len ), 0 ); |
if( ret < 0 ) |
{ |
/*if( net_would_block( ctx ) != 0 ) |
return( MBEDTLS_ERR_SSL_WANT_READ ); |
if( errno == EPIPE || errno == ECONNRESET ) |
return( MBEDTLS_ERR_NET_CONN_RESET ); |
if( errno == EINTR ) |
return( MBEDTLS_ERR_SSL_WANT_READ ); |
*/ |
return( MBEDTLS_ERR_NET_RECV_FAILED ); |
} |
return( ret ); |
} |
/*******/ |
/* |
* Write at most 'len' characters |
*/ |
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) |
{ |
int ret; |
int fd = ((mbedtls_net_context *) ctx)->fd; |
if( fd < 0 ) |
return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); |
ret = (int) send( fd, (char*)( buf ), (int)( len ), 0 ); |
if( ret < 0 ) |
{ |
/*if( net_would_block( ctx ) != 0 ) |
return( MBEDTLS_ERR_SSL_WANT_WRITE ); |
if( errno == EPIPE || errno == ECONNRESET ) |
return( MBEDTLS_ERR_NET_CONN_RESET ); |
if( errno == EINTR ) |
return( MBEDTLS_ERR_SSL_WANT_WRITE ); |
*/ |
return( MBEDTLS_ERR_NET_SEND_FAILED ); |
} |
return( ret ); |
} |
/* |
* Gracefully close the connection |
*/ |
void mbedtls_net_free( mbedtls_net_context *ctx ) |
{ |
if( ctx->fd == -1 ) |
return; |
//shutdown( ctx->fd, 2 ); |
closesocket( ctx->fd ); |
ctx->fd = -1; |
} |
#endif /* MBEDTLS_NET_C */ |
/programs/develop/libraries/kos_mbedtls/library/nist_kw.c |
---|
0,0 → 1,757 |
/* |
* Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes |
* only |
* |
* Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of Mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* Definition of Key Wrapping: |
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf |
* RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" |
* RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" |
* |
* Note: RFC 3394 defines different methodology for intermediate operations for |
* the wrapping and unwrapping operation than the definition in NIST SP 800-38F. |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_NIST_KW_C) |
#include "mbedtls/nist_kw.h" |
#include "mbedtls/platform_util.h" |
#include <stdint.h> |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ |
#if !defined(MBEDTLS_NIST_KW_ALT) |
#define KW_SEMIBLOCK_LENGTH 8 |
#define MIN_SEMIBLOCKS_COUNT 3 |
/* constant-time buffer comparison */ |
static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) |
{ |
size_t i; |
volatile const unsigned char *A = (volatile const unsigned char *) a; |
volatile const unsigned char *B = (volatile const unsigned char *) b; |
volatile unsigned char diff = 0; |
for( i = 0; i < n; i++ ) |
{ |
/* Read volatile data in order before computing diff. |
* This avoids IAR compiler warning: |
* 'the order of volatile accesses is undefined ..' */ |
unsigned char x = A[i], y = B[i]; |
diff |= x ^ y; |
} |
return( diff ); |
} |
/*! The 64-bit default integrity check value (ICV) for KW mode. */ |
static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; |
/*! The 32-bit default integrity check value (ICV) for KWP mode. */ |
static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
do { \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} while( 0 ) |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
do { \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} while( 0 ) |
#endif |
/* |
* Initialize context |
*/ |
void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); |
} |
int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, |
mbedtls_cipher_id_t cipher, |
const unsigned char *key, |
unsigned int keybits, |
const int is_wrap ) |
{ |
int ret; |
const mbedtls_cipher_info_t *cipher_info; |
cipher_info = mbedtls_cipher_info_from_values( cipher, |
keybits, |
MBEDTLS_MODE_ECB ); |
if( cipher_info == NULL ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
if( cipher_info->block_size != 16 ) |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
/* |
* SP 800-38F currently defines AES cipher as the only block cipher allowed: |
* "For KW and KWP, the underlying block cipher shall be approved, and the |
* block size shall be 128 bits. Currently, the AES block cipher, with key |
* lengths of 128, 192, or 256 bits, is the only block cipher that fits |
* this profile." |
* Currently we don't support other 128 bit block ciphers for key wrapping, |
* such as Camellia and Aria. |
*/ |
if( cipher != MBEDTLS_CIPHER_ID_AES ) |
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); |
mbedtls_cipher_free( &ctx->cipher_ctx ); |
if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, |
is_wrap ? MBEDTLS_ENCRYPT : |
MBEDTLS_DECRYPT ) |
) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
/* |
* Free context |
*/ |
void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) |
{ |
mbedtls_cipher_free( &ctx->cipher_ctx ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); |
} |
/* |
* Helper function for Xoring the uint64_t "t" with the encrypted A. |
* Defined in NIST SP 800-38F section 6.1 |
*/ |
static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) |
{ |
size_t i = 0; |
for( i = 0; i < sizeof( t ); i++ ) |
{ |
A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; |
} |
} |
/* |
* KW-AE as defined in SP 800-38F section 6.2 |
* KWP-AE as defined in SP 800-38F section 6.3 |
*/ |
int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, |
mbedtls_nist_kw_mode_t mode, |
const unsigned char *input, size_t in_len, |
unsigned char *output, size_t *out_len, size_t out_size ) |
{ |
int ret = 0; |
size_t semiblocks = 0; |
size_t s; |
size_t olen, padlen = 0; |
uint64_t t = 0; |
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; |
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; |
unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; |
unsigned char *A = output; |
*out_len = 0; |
/* |
* Generate the String to work on |
*/ |
if( mode == MBEDTLS_KW_MODE_KW ) |
{ |
if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
/* |
* According to SP 800-38F Table 1, the plaintext length for KW |
* must be between 2 to 2^54-1 semiblocks inclusive. |
*/ |
if( in_len < 16 || |
#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 |
in_len > 0x1FFFFFFFFFFFFF8 || |
#endif |
in_len % KW_SEMIBLOCK_LENGTH != 0 ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); |
memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); |
} |
else |
{ |
if( in_len % 8 != 0 ) |
{ |
padlen = ( 8 - ( in_len % 8 ) ); |
} |
if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
/* |
* According to SP 800-38F Table 1, the plaintext length for KWP |
* must be between 1 and 2^32-1 octets inclusive. |
*/ |
if( in_len < 1 |
#if SIZE_MAX > 0xFFFFFFFF |
|| in_len > 0xFFFFFFFF |
#endif |
) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); |
PUT_UINT32_BE( ( in_len & 0xffffffff ), output, |
KW_SEMIBLOCK_LENGTH / 2 ); |
memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); |
memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); |
} |
semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; |
s = 6 * ( semiblocks - 1 ); |
if( mode == MBEDTLS_KW_MODE_KWP |
&& in_len <= KW_SEMIBLOCK_LENGTH ) |
{ |
memcpy( inbuff, output, 16 ); |
ret = mbedtls_cipher_update( &ctx->cipher_ctx, |
inbuff, 16, output, &olen ); |
if( ret != 0 ) |
goto cleanup; |
} |
else |
{ |
/* |
* Do the wrapping function W, as defined in RFC 3394 section 2.2.1 |
*/ |
if( semiblocks < MIN_SEMIBLOCKS_COUNT ) |
{ |
ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
goto cleanup; |
} |
/* Calculate intermediate values */ |
for( t = 1; t <= s; t++ ) |
{ |
memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); |
memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); |
ret = mbedtls_cipher_update( &ctx->cipher_ctx, |
inbuff, 16, outbuff, &olen ); |
if( ret != 0 ) |
goto cleanup; |
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); |
calc_a_xor_t( A, t ); |
memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); |
R2 += KW_SEMIBLOCK_LENGTH; |
if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) |
R2 = output + KW_SEMIBLOCK_LENGTH; |
} |
} |
*out_len = semiblocks * KW_SEMIBLOCK_LENGTH; |
cleanup: |
if( ret != 0) |
{ |
memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); |
} |
mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); |
mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); |
return( ret ); |
} |
/* |
* W-1 function as defined in RFC 3394 section 2.2.2 |
* This function assumes the following: |
* 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. |
* 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. |
* 3. Minimal number of semiblocks is 3. |
* 4. A is a buffer to hold the first semiblock of the input buffer. |
*/ |
static int unwrap( mbedtls_nist_kw_context *ctx, |
const unsigned char *input, size_t semiblocks, |
unsigned char A[KW_SEMIBLOCK_LENGTH], |
unsigned char *output, size_t* out_len ) |
{ |
int ret = 0; |
const size_t s = 6 * ( semiblocks - 1 ); |
size_t olen; |
uint64_t t = 0; |
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; |
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; |
unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; |
*out_len = 0; |
if( semiblocks < MIN_SEMIBLOCKS_COUNT ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
memcpy( A, input, KW_SEMIBLOCK_LENGTH ); |
memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); |
/* Calculate intermediate values */ |
for( t = s; t >= 1; t-- ) |
{ |
calc_a_xor_t( A, t ); |
memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); |
memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); |
ret = mbedtls_cipher_update( &ctx->cipher_ctx, |
inbuff, 16, outbuff, &olen ); |
if( ret != 0 ) |
goto cleanup; |
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); |
/* Set R as LSB64 of outbuff */ |
memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); |
if( R == output ) |
R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; |
else |
R -= KW_SEMIBLOCK_LENGTH; |
} |
*out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; |
cleanup: |
if( ret != 0) |
memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); |
mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); |
mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); |
return( ret ); |
} |
/* |
* KW-AD as defined in SP 800-38F section 6.2 |
* KWP-AD as defined in SP 800-38F section 6.3 |
*/ |
int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, |
mbedtls_nist_kw_mode_t mode, |
const unsigned char *input, size_t in_len, |
unsigned char *output, size_t *out_len, size_t out_size ) |
{ |
int ret = 0; |
size_t i, olen; |
unsigned char A[KW_SEMIBLOCK_LENGTH]; |
unsigned char diff, bad_padding = 0; |
*out_len = 0; |
if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
if( mode == MBEDTLS_KW_MODE_KW ) |
{ |
/* |
* According to SP 800-38F Table 1, the ciphertext length for KW |
* must be between 3 to 2^54 semiblocks inclusive. |
*/ |
if( in_len < 24 || |
#if SIZE_MAX > 0x200000000000000 |
in_len > 0x200000000000000 || |
#endif |
in_len % KW_SEMIBLOCK_LENGTH != 0 ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, |
A, output, out_len ); |
if( ret != 0 ) |
goto cleanup; |
/* Check ICV in "constant-time" */ |
diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); |
if( diff != 0 ) |
{ |
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
goto cleanup; |
} |
} |
else if( mode == MBEDTLS_KW_MODE_KWP ) |
{ |
size_t padlen = 0; |
uint32_t Plen; |
/* |
* According to SP 800-38F Table 1, the ciphertext length for KWP |
* must be between 2 to 2^29 semiblocks inclusive. |
*/ |
if( in_len < KW_SEMIBLOCK_LENGTH * 2 || |
#if SIZE_MAX > 0x100000000 |
in_len > 0x100000000 || |
#endif |
in_len % KW_SEMIBLOCK_LENGTH != 0 ) |
{ |
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); |
} |
if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) |
{ |
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; |
ret = mbedtls_cipher_update( &ctx->cipher_ctx, |
input, 16, outbuff, &olen ); |
if( ret != 0 ) |
goto cleanup; |
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); |
memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); |
mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); |
*out_len = KW_SEMIBLOCK_LENGTH; |
} |
else |
{ |
/* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ |
ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, |
A, output, out_len ); |
if( ret != 0 ) |
goto cleanup; |
} |
/* Check ICV in "constant-time" */ |
diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); |
if( diff != 0 ) |
{ |
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
} |
GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); |
/* |
* Plen is the length of the plaintext, when the input is valid. |
* If Plen is larger than the plaintext and padding, padlen will be |
* larger than 8, because of the type wrap around. |
*/ |
padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; |
if ( padlen > 7 ) |
{ |
padlen &= 7; |
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
} |
/* Check padding in "constant-time" */ |
for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) |
{ |
if( i >= KW_SEMIBLOCK_LENGTH - padlen ) |
diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; |
else |
bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; |
} |
if( diff != 0 ) |
{ |
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
} |
if( ret != 0 ) |
{ |
goto cleanup; |
} |
memset( output + Plen, 0, padlen ); |
*out_len = Plen; |
} |
else |
{ |
ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; |
goto cleanup; |
} |
cleanup: |
if( ret != 0 ) |
{ |
memset( output, 0, *out_len ); |
*out_len = 0; |
} |
mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); |
mbedtls_platform_zeroize( &diff, sizeof( diff ) ); |
mbedtls_platform_zeroize( A, sizeof( A ) ); |
return( ret ); |
} |
#endif /* !MBEDTLS_NIST_KW_ALT */ |
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) |
#define KW_TESTS 3 |
/* |
* Test vectors taken from NIST |
* https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW |
*/ |
static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; |
static const unsigned char kw_key[KW_TESTS][32] = { |
{ 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, |
0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, |
{ 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, |
0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, |
0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, |
{ 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, |
0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, |
0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, |
0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } |
}; |
static const unsigned char kw_msg[KW_TESTS][40] = { |
{ 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, |
0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, |
{ 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, |
0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, |
0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, |
0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, |
0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, |
{ 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, |
0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, |
0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } |
}; |
static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; |
static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; |
static const unsigned char kw_res[KW_TESTS][48] = { |
{ 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, |
0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, |
0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, |
{ 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, |
0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, |
0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, |
0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, |
0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, |
0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, |
{ 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, |
0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, |
0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, |
0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } |
}; |
static const unsigned char kwp_key[KW_TESTS][32] = { |
{ 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, |
0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, |
{ 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, |
0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, |
0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, |
{ 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, |
0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, |
0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, |
0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } |
}; |
static const unsigned char kwp_msg[KW_TESTS][31] = { |
{ 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, |
0x96 }, |
{ 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, |
0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, |
0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, |
0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, |
{ 0xd1 } |
}; |
static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; |
static const unsigned char kwp_res[KW_TESTS][48] = { |
{ 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, |
0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, |
0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, |
{ 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, |
0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, |
0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, |
0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, |
0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, |
{ 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, |
0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } |
}; |
static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; |
int mbedtls_nist_kw_self_test( int verbose ) |
{ |
mbedtls_nist_kw_context ctx; |
unsigned char out[48]; |
size_t olen; |
int i; |
int ret = 0; |
mbedtls_nist_kw_init( &ctx ); |
for( i = 0; i < KW_TESTS; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); |
ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, |
kw_key[i], key_len[i] * 8, 1 ); |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " KW: setup failed " ); |
goto end; |
} |
ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], |
kw_msg_len[i], out, &olen, sizeof( out ) ); |
if( ret != 0 || kw_out_len[i] != olen || |
memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed. "); |
ret = 1; |
goto end; |
} |
if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, |
kw_key[i], key_len[i] * 8, 0 ) ) |
!= 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " KW: setup failed "); |
goto end; |
} |
ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, |
out, olen, out, &olen, sizeof( out ) ); |
if( ret != 0 || olen != kw_msg_len[i] || |
memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto end; |
} |
if( verbose != 0 ) |
mbedtls_printf( " passed\n" ); |
} |
for( i = 0; i < KW_TESTS; i++ ) |
{ |
olen = sizeof( out ); |
if( verbose != 0 ) |
mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); |
ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], |
key_len[i] * 8, 1 ); |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " KWP: setup failed " ); |
goto end; |
} |
ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], |
kwp_msg_len[i], out, &olen, sizeof( out ) ); |
if( ret != 0 || kwp_out_len[i] != olen || |
memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed. "); |
ret = 1; |
goto end; |
} |
if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, |
kwp_key[i], key_len[i] * 8, 0 ) ) |
!= 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " KWP: setup failed "); |
goto end; |
} |
ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, |
olen, out, &olen, sizeof( out ) ); |
if( ret != 0 || olen != kwp_msg_len[i] || |
memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed. "); |
ret = 1; |
goto end; |
} |
if( verbose != 0 ) |
mbedtls_printf( " passed\n" ); |
} |
end: |
mbedtls_nist_kw_free( &ctx ); |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ |
#endif /* MBEDTLS_NIST_KW_C */ |
/programs/develop/libraries/kos_mbedtls/library/oid.c |
---|
0,0 → 1,760 |
/** |
* \file oid.c |
* |
* \brief Object Identifier (OID) database |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_OID_C) |
#include "mbedtls/oid.h" |
#include "mbedtls/rsa.h" |
#include <stdio.h> |
#include <string.h> |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#define mbedtls_snprintf snprintf |
#endif |
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) |
#include "mbedtls/x509.h" |
#endif |
/* |
* Macro to automatically add the size of #define'd OIDs |
*/ |
#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) |
/* |
* Macro to generate an internal function for oid_XXX_from_asn1() (used by |
* the other functions) |
*/ |
#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ |
static const TYPE_T * oid_ ## NAME ## _from_asn1( \ |
const mbedtls_asn1_buf *oid ) \ |
{ \ |
const TYPE_T *p = (LIST); \ |
const mbedtls_oid_descriptor_t *cur = \ |
(const mbedtls_oid_descriptor_t *) p; \ |
if( p == NULL || oid == NULL ) return( NULL ); \ |
while( cur->asn1 != NULL ) { \ |
if( cur->asn1_len == oid->len && \ |
memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ |
return( p ); \ |
} \ |
p++; \ |
cur = (const mbedtls_oid_descriptor_t *) p; \ |
} \ |
return( NULL ); \ |
} |
/* |
* Macro to generate a function for retrieving a single attribute from the |
* descriptor of an mbedtls_oid_descriptor_t wrapper. |
*/ |
#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ |
int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ |
{ \ |
const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ |
if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ |
*ATTR1 = data->descriptor.ATTR1; \ |
return( 0 ); \ |
} |
/* |
* Macro to generate a function for retrieving a single attribute from an |
* mbedtls_oid_descriptor_t wrapper. |
*/ |
#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ |
int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ |
{ \ |
const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ |
if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ |
*ATTR1 = data->ATTR1; \ |
return( 0 ); \ |
} |
/* |
* Macro to generate a function for retrieving two attributes from an |
* mbedtls_oid_descriptor_t wrapper. |
*/ |
#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ |
ATTR2_TYPE, ATTR2) \ |
int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ |
ATTR2_TYPE * ATTR2 ) \ |
{ \ |
const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ |
if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ |
*(ATTR1) = data->ATTR1; \ |
*(ATTR2) = data->ATTR2; \ |
return( 0 ); \ |
} |
/* |
* Macro to generate a function for retrieving the OID based on a single |
* attribute from a mbedtls_oid_descriptor_t wrapper. |
*/ |
#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ |
int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ |
{ \ |
const TYPE_T *cur = (LIST); \ |
while( cur->descriptor.asn1 != NULL ) { \ |
if( cur->ATTR1 == (ATTR1) ) { \ |
*oid = cur->descriptor.asn1; \ |
*olen = cur->descriptor.asn1_len; \ |
return( 0 ); \ |
} \ |
cur++; \ |
} \ |
return( MBEDTLS_ERR_OID_NOT_FOUND ); \ |
} |
/* |
* Macro to generate a function for retrieving the OID based on two |
* attributes from a mbedtls_oid_descriptor_t wrapper. |
*/ |
#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ |
ATTR2_TYPE, ATTR2) \ |
int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ |
size_t *olen ) \ |
{ \ |
const TYPE_T *cur = (LIST); \ |
while( cur->descriptor.asn1 != NULL ) { \ |
if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \ |
*oid = cur->descriptor.asn1; \ |
*olen = cur->descriptor.asn1_len; \ |
return( 0 ); \ |
} \ |
cur++; \ |
} \ |
return( MBEDTLS_ERR_OID_NOT_FOUND ); \ |
} |
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) |
/* |
* For X520 attribute types |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
const char *short_name; |
} oid_x520_attr_t; |
static const oid_x520_attr_t oid_x520_attr_type[] = |
{ |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, |
"CN", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, |
"C", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, |
"L", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, |
"ST", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, |
"O", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, |
"OU", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, |
"emailAddress", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, |
"serialNumber", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, |
"postalAddress", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, |
"postalCode", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, |
"SN", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, |
"GN", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, |
"initials", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, |
"generationQualifier", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, |
"title", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, |
"dnQualifier", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, |
"pseudonym", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, |
"DC", |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, |
"uniqueIdentifier", |
}, |
{ |
{ NULL, 0, NULL, NULL }, |
NULL, |
} |
}; |
FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) |
FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) |
/* |
* For X509 extensions |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
int ext_type; |
} oid_x509_ext_t; |
static const oid_x509_ext_t oid_x509_ext[] = |
{ |
{ |
{ ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, |
MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, |
MBEDTLS_X509_EXT_KEY_USAGE, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, |
MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, |
MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, |
MBEDTLS_X509_EXT_NS_CERT_TYPE, |
}, |
{ |
{ NULL, 0, NULL, NULL }, |
0, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) |
FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) |
static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = |
{ |
{ ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, |
{ ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, |
{ ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, |
{ ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, |
{ ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, |
{ ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, |
{ NULL, 0, NULL, NULL }, |
}; |
FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) |
FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) |
#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ |
#if defined(MBEDTLS_MD_C) |
/* |
* For SignatureAlgorithmIdentifier |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
mbedtls_md_type_t md_alg; |
mbedtls_pk_type_t pk_alg; |
} oid_sig_alg_t; |
static const oid_sig_alg_t oid_sig_alg[] = |
{ |
#if defined(MBEDTLS_RSA_C) |
#if defined(MBEDTLS_MD2_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, |
MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, |
}, |
#endif /* MBEDTLS_MD2_C */ |
#if defined(MBEDTLS_MD4_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, |
MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, |
}, |
#endif /* MBEDTLS_MD4_C */ |
#if defined(MBEDTLS_MD5_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, |
MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, |
}, |
#endif /* MBEDTLS_MD5_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, |
MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, |
}, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, |
MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, |
MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, |
}, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, |
MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, |
MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, |
}, |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, |
MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, |
}, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECDSA_C) |
#if defined(MBEDTLS_SHA1_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, |
MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, |
}, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, |
MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, |
MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, |
}, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, |
MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, |
MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, |
}, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_ECDSA_C */ |
#if defined(MBEDTLS_RSA_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, |
MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, |
}, |
#endif /* MBEDTLS_RSA_C */ |
{ |
{ NULL, 0, NULL, NULL }, |
MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) |
FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) |
FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) |
FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) |
#endif /* MBEDTLS_MD_C */ |
/* |
* For PublicKeyInfo (PKCS1, RFC 5480) |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
mbedtls_pk_type_t pk_alg; |
} oid_pk_alg_t; |
static const oid_pk_alg_t oid_pk_alg[] = |
{ |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, |
MBEDTLS_PK_RSA, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, |
MBEDTLS_PK_ECKEY, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, |
MBEDTLS_PK_ECKEY_DH, |
}, |
{ |
{ NULL, 0, NULL, NULL }, |
MBEDTLS_PK_NONE, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) |
FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) |
FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) |
#if defined(MBEDTLS_ECP_C) |
/* |
* For namedCurve (RFC 5480) |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
mbedtls_ecp_group_id grp_id; |
} oid_ecp_grp_t; |
static const oid_ecp_grp_t oid_ecp_grp[] = |
{ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, |
MBEDTLS_ECP_DP_SECP192R1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, |
MBEDTLS_ECP_DP_SECP224R1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, |
MBEDTLS_ECP_DP_SECP256R1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, |
MBEDTLS_ECP_DP_SECP384R1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, |
MBEDTLS_ECP_DP_SECP521R1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, |
MBEDTLS_ECP_DP_SECP192K1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, |
MBEDTLS_ECP_DP_SECP224K1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, |
MBEDTLS_ECP_DP_SECP256K1, |
}, |
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, |
MBEDTLS_ECP_DP_BP256R1, |
}, |
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, |
MBEDTLS_ECP_DP_BP384R1, |
}, |
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) |
{ |
{ ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, |
MBEDTLS_ECP_DP_BP512R1, |
}, |
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ |
{ |
{ NULL, 0, NULL, NULL }, |
MBEDTLS_ECP_DP_NONE, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) |
FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) |
FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_CIPHER_C) |
/* |
* For PKCS#5 PBES2 encryption algorithm |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
mbedtls_cipher_type_t cipher_alg; |
} oid_cipher_alg_t; |
static const oid_cipher_alg_t oid_cipher_alg[] = |
{ |
{ |
{ ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, |
MBEDTLS_CIPHER_DES_CBC, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, |
MBEDTLS_CIPHER_DES_EDE3_CBC, |
}, |
{ |
{ NULL, 0, NULL, NULL }, |
MBEDTLS_CIPHER_NONE, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) |
FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) |
#endif /* MBEDTLS_CIPHER_C */ |
#if defined(MBEDTLS_MD_C) |
/* |
* For digestAlgorithm |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
mbedtls_md_type_t md_alg; |
} oid_md_alg_t; |
static const oid_md_alg_t oid_md_alg[] = |
{ |
#if defined(MBEDTLS_MD2_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, |
MBEDTLS_MD_MD2, |
}, |
#endif /* MBEDTLS_MD2_C */ |
#if defined(MBEDTLS_MD4_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, |
MBEDTLS_MD_MD4, |
}, |
#endif /* MBEDTLS_MD4_C */ |
#if defined(MBEDTLS_MD5_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, |
MBEDTLS_MD_MD5, |
}, |
#endif /* MBEDTLS_MD5_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, |
MBEDTLS_MD_SHA1, |
}, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, |
MBEDTLS_MD_SHA224, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, |
MBEDTLS_MD_SHA256, |
}, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, |
MBEDTLS_MD_SHA384, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, |
MBEDTLS_MD_SHA512, |
}, |
#endif /* MBEDTLS_SHA512_C */ |
{ |
{ NULL, 0, NULL, NULL }, |
MBEDTLS_MD_NONE, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) |
FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) |
FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) |
/* |
* For HMAC digestAlgorithm |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
mbedtls_md_type_t md_hmac; |
} oid_md_hmac_t; |
static const oid_md_hmac_t oid_md_hmac[] = |
{ |
#if defined(MBEDTLS_SHA1_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, |
MBEDTLS_MD_SHA1, |
}, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, |
MBEDTLS_MD_SHA224, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, |
MBEDTLS_MD_SHA256, |
}, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ |
{ ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, |
MBEDTLS_MD_SHA384, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, |
MBEDTLS_MD_SHA512, |
}, |
#endif /* MBEDTLS_SHA512_C */ |
{ |
{ NULL, 0, NULL, NULL }, |
MBEDTLS_MD_NONE, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) |
FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) |
#endif /* MBEDTLS_MD_C */ |
#if defined(MBEDTLS_PKCS12_C) |
/* |
* For PKCS#12 PBEs |
*/ |
typedef struct { |
mbedtls_oid_descriptor_t descriptor; |
mbedtls_md_type_t md_alg; |
mbedtls_cipher_type_t cipher_alg; |
} oid_pkcs12_pbe_alg_t; |
static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = |
{ |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, |
MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, |
}, |
{ |
{ ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, |
MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, |
}, |
{ |
{ NULL, 0, NULL, NULL }, |
MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, |
}, |
}; |
FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) |
FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) |
#endif /* MBEDTLS_PKCS12_C */ |
#define OID_SAFE_SNPRINTF \ |
do { \ |
if( ret < 0 || (size_t) ret >= n ) \ |
return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ |
\ |
n -= (size_t) ret; \ |
p += (size_t) ret; \ |
} while( 0 ) |
/* Return the x.y.z.... style numeric string for the given OID */ |
int mbedtls_oid_get_numeric_string( char *buf, size_t size, |
const mbedtls_asn1_buf *oid ) |
{ |
int ret; |
size_t i, n; |
unsigned int value; |
char *p; |
p = buf; |
n = size; |
/* First byte contains first two dots */ |
if( oid->len > 0 ) |
{ |
ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); |
OID_SAFE_SNPRINTF; |
} |
value = 0; |
for( i = 1; i < oid->len; i++ ) |
{ |
/* Prevent overflow in value. */ |
if( ( ( value << 7 ) >> 7 ) != value ) |
return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); |
value <<= 7; |
value += oid->p[i] & 0x7F; |
if( !( oid->p[i] & 0x80 ) ) |
{ |
/* Last byte */ |
ret = mbedtls_snprintf( p, n, ".%d", value ); |
OID_SAFE_SNPRINTF; |
value = 0; |
} |
} |
return( (int) ( size - n ) ); |
} |
#endif /* MBEDTLS_OID_C */ |
/programs/develop/libraries/kos_mbedtls/library/padlock.c |
---|
0,0 → 1,172 |
/* |
* VIA PadLock support functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* This implementation is based on the VIA PadLock Programming Guide: |
* |
* http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ |
* programming_guide.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PADLOCK_C) |
#include "mbedtls/padlock.h" |
#include <string.h> |
#ifndef asm |
#define asm __asm |
#endif |
#if defined(MBEDTLS_HAVE_X86) |
/* |
* PadLock detection routine |
*/ |
int mbedtls_padlock_has_support( int feature ) |
{ |
static int flags = -1; |
int ebx = 0, edx = 0; |
if( flags == -1 ) |
{ |
asm( "movl %%ebx, %0 \n\t" |
"movl $0xC0000000, %%eax \n\t" |
"cpuid \n\t" |
"cmpl $0xC0000001, %%eax \n\t" |
"movl $0, %%edx \n\t" |
"jb unsupported \n\t" |
"movl $0xC0000001, %%eax \n\t" |
"cpuid \n\t" |
"unsupported: \n\t" |
"movl %%edx, %1 \n\t" |
"movl %2, %%ebx \n\t" |
: "=m" (ebx), "=m" (edx) |
: "m" (ebx) |
: "eax", "ecx", "edx" ); |
flags = edx; |
} |
return( flags & feature ); |
} |
/* |
* PadLock AES-ECB block en(de)cryption |
*/ |
int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, |
int mode, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
int ebx = 0; |
uint32_t *rk; |
uint32_t *blk; |
uint32_t *ctrl; |
unsigned char buf[256]; |
rk = ctx->rk; |
blk = MBEDTLS_PADLOCK_ALIGN16( buf ); |
memcpy( blk, input, 16 ); |
ctrl = blk + 4; |
*ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); |
asm( "pushfl \n\t" |
"popfl \n\t" |
"movl %%ebx, %0 \n\t" |
"movl $1, %%ecx \n\t" |
"movl %2, %%edx \n\t" |
"movl %3, %%ebx \n\t" |
"movl %4, %%esi \n\t" |
"movl %4, %%edi \n\t" |
".byte 0xf3,0x0f,0xa7,0xc8 \n\t" |
"movl %1, %%ebx \n\t" |
: "=m" (ebx) |
: "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) |
: "memory", "ecx", "edx", "esi", "edi" ); |
memcpy( output, blk, 16 ); |
return( 0 ); |
} |
/* |
* PadLock AES-CBC buffer en(de)cryption |
*/ |
int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, |
int mode, |
size_t length, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ebx = 0; |
size_t count; |
uint32_t *rk; |
uint32_t *iw; |
uint32_t *ctrl; |
unsigned char buf[256]; |
if( ( (long) input & 15 ) != 0 || |
( (long) output & 15 ) != 0 ) |
return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); |
rk = ctx->rk; |
iw = MBEDTLS_PADLOCK_ALIGN16( buf ); |
memcpy( iw, iv, 16 ); |
ctrl = iw + 4; |
*ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); |
count = ( length + 15 ) >> 4; |
asm( "pushfl \n\t" |
"popfl \n\t" |
"movl %%ebx, %0 \n\t" |
"movl %2, %%ecx \n\t" |
"movl %3, %%edx \n\t" |
"movl %4, %%ebx \n\t" |
"movl %5, %%esi \n\t" |
"movl %6, %%edi \n\t" |
"movl %7, %%eax \n\t" |
".byte 0xf3,0x0f,0xa7,0xd0 \n\t" |
"movl %1, %%ebx \n\t" |
: "=m" (ebx) |
: "m" (ebx), "m" (count), "m" (ctrl), |
"m" (rk), "m" (input), "m" (output), "m" (iw) |
: "memory", "eax", "ecx", "edx", "esi", "edi" ); |
memcpy( iv, iw, 16 ); |
return( 0 ); |
} |
#endif /* MBEDTLS_HAVE_X86 */ |
#endif /* MBEDTLS_PADLOCK_C */ |
/programs/develop/libraries/kos_mbedtls/library/pem.c |
---|
0,0 → 1,492 |
/* |
* Privacy Enhanced Mail (PEM) decoding |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) |
#include "mbedtls/pem.h" |
#include "mbedtls/base64.h" |
#include "mbedtls/des.h" |
#include "mbedtls/aes.h" |
#include "mbedtls/md5.h" |
#include "mbedtls/cipher.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#if defined(MBEDTLS_PEM_PARSE_C) |
void mbedtls_pem_init( mbedtls_pem_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_pem_context ) ); |
} |
#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ |
( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) |
/* |
* Read a 16-byte hex string and convert it to binary |
*/ |
static int pem_get_iv( const unsigned char *s, unsigned char *iv, |
size_t iv_len ) |
{ |
size_t i, j, k; |
memset( iv, 0, iv_len ); |
for( i = 0; i < iv_len * 2; i++, s++ ) |
{ |
if( *s >= '0' && *s <= '9' ) j = *s - '0'; else |
if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else |
if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else |
return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); |
k = ( ( i & 1 ) != 0 ) ? j : j << 4; |
iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); |
} |
return( 0 ); |
} |
static int pem_pbkdf1( unsigned char *key, size_t keylen, |
unsigned char *iv, |
const unsigned char *pwd, size_t pwdlen ) |
{ |
mbedtls_md5_context md5_ctx; |
unsigned char md5sum[16]; |
size_t use_len; |
int ret; |
mbedtls_md5_init( &md5_ctx ); |
/* |
* key[ 0..15] = MD5(pwd || IV) |
*/ |
if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) |
goto exit; |
if( keylen <= 16 ) |
{ |
memcpy( key, md5sum, keylen ); |
goto exit; |
} |
memcpy( key, md5sum, 16 ); |
/* |
* key[16..23] = MD5(key[ 0..15] || pwd || IV]) |
*/ |
if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) |
goto exit; |
use_len = 16; |
if( keylen < 32 ) |
use_len = keylen - 16; |
memcpy( key + 16, md5sum, use_len ); |
exit: |
mbedtls_md5_free( &md5_ctx ); |
mbedtls_platform_zeroize( md5sum, 16 ); |
return( ret ); |
} |
#if defined(MBEDTLS_DES_C) |
/* |
* Decrypt with DES-CBC, using PBKDF1 for key derivation |
*/ |
static int pem_des_decrypt( unsigned char des_iv[8], |
unsigned char *buf, size_t buflen, |
const unsigned char *pwd, size_t pwdlen ) |
{ |
mbedtls_des_context des_ctx; |
unsigned char des_key[8]; |
int ret; |
mbedtls_des_init( &des_ctx ); |
if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) |
goto exit; |
ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, |
des_iv, buf, buf ); |
exit: |
mbedtls_des_free( &des_ctx ); |
mbedtls_platform_zeroize( des_key, 8 ); |
return( ret ); |
} |
/* |
* Decrypt with 3DES-CBC, using PBKDF1 for key derivation |
*/ |
static int pem_des3_decrypt( unsigned char des3_iv[8], |
unsigned char *buf, size_t buflen, |
const unsigned char *pwd, size_t pwdlen ) |
{ |
mbedtls_des3_context des3_ctx; |
unsigned char des3_key[24]; |
int ret; |
mbedtls_des3_init( &des3_ctx ); |
if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) |
goto exit; |
ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, |
des3_iv, buf, buf ); |
exit: |
mbedtls_des3_free( &des3_ctx ); |
mbedtls_platform_zeroize( des3_key, 24 ); |
return( ret ); |
} |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_AES_C) |
/* |
* Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation |
*/ |
static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, |
unsigned char *buf, size_t buflen, |
const unsigned char *pwd, size_t pwdlen ) |
{ |
mbedtls_aes_context aes_ctx; |
unsigned char aes_key[32]; |
int ret; |
mbedtls_aes_init( &aes_ctx ); |
if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) |
goto exit; |
ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, |
aes_iv, buf, buf ); |
exit: |
mbedtls_aes_free( &aes_ctx ); |
mbedtls_platform_zeroize( aes_key, keylen ); |
return( ret ); |
} |
#endif /* MBEDTLS_AES_C */ |
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && |
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ |
int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, |
const unsigned char *data, const unsigned char *pwd, |
size_t pwdlen, size_t *use_len ) |
{ |
int ret, enc; |
size_t len; |
unsigned char *buf; |
const unsigned char *s1, *s2, *end; |
#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ |
( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) |
unsigned char pem_iv[16]; |
mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; |
#else |
((void) pwd); |
((void) pwdlen); |
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && |
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ |
if( ctx == NULL ) |
return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); |
s1 = (unsigned char *) strstr( (const char *) data, header ); |
if( s1 == NULL ) |
return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); |
s2 = (unsigned char *) strstr( (const char *) data, footer ); |
if( s2 == NULL || s2 <= s1 ) |
return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); |
s1 += strlen( header ); |
if( *s1 == ' ' ) s1++; |
if( *s1 == '\r' ) s1++; |
if( *s1 == '\n' ) s1++; |
else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); |
end = s2; |
end += strlen( footer ); |
if( *end == ' ' ) end++; |
if( *end == '\r' ) end++; |
if( *end == '\n' ) end++; |
*use_len = end - data; |
enc = 0; |
if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) |
{ |
#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ |
( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) |
enc++; |
s1 += 22; |
if( *s1 == '\r' ) s1++; |
if( *s1 == '\n' ) s1++; |
else return( MBEDTLS_ERR_PEM_INVALID_DATA ); |
#if defined(MBEDTLS_DES_C) |
if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) |
{ |
enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; |
s1 += 23; |
if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) |
return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); |
s1 += 16; |
} |
else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) |
{ |
enc_alg = MBEDTLS_CIPHER_DES_CBC; |
s1 += 18; |
if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) |
return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); |
s1 += 16; |
} |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_AES_C) |
if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) |
{ |
if( s2 - s1 < 22 ) |
return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); |
else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) |
enc_alg = MBEDTLS_CIPHER_AES_128_CBC; |
else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) |
enc_alg = MBEDTLS_CIPHER_AES_192_CBC; |
else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) |
enc_alg = MBEDTLS_CIPHER_AES_256_CBC; |
else |
return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); |
s1 += 22; |
if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) |
return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); |
s1 += 32; |
} |
#endif /* MBEDTLS_AES_C */ |
if( enc_alg == MBEDTLS_CIPHER_NONE ) |
return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); |
if( *s1 == '\r' ) s1++; |
if( *s1 == '\n' ) s1++; |
else return( MBEDTLS_ERR_PEM_INVALID_DATA ); |
#else |
return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); |
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && |
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ |
} |
if( s1 >= s2 ) |
return( MBEDTLS_ERR_PEM_INVALID_DATA ); |
ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); |
if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) |
return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); |
if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) |
return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); |
if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) |
{ |
mbedtls_platform_zeroize( buf, len ); |
mbedtls_free( buf ); |
return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); |
} |
if( enc != 0 ) |
{ |
#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ |
( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) |
if( pwd == NULL ) |
{ |
mbedtls_platform_zeroize( buf, len ); |
mbedtls_free( buf ); |
return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); |
} |
ret = 0; |
#if defined(MBEDTLS_DES_C) |
if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) |
ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); |
else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) |
ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_AES_C) |
if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) |
ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); |
else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) |
ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); |
else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) |
ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); |
#endif /* MBEDTLS_AES_C */ |
if( ret != 0 ) |
{ |
mbedtls_free( buf ); |
return( ret ); |
} |
/* |
* The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 |
* length bytes (allow 4 to be sure) in all known use cases. |
* |
* Use that as a heuristic to try to detect password mismatches. |
*/ |
if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) |
{ |
mbedtls_platform_zeroize( buf, len ); |
mbedtls_free( buf ); |
return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); |
} |
#else |
mbedtls_platform_zeroize( buf, len ); |
mbedtls_free( buf ); |
return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); |
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && |
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ |
} |
ctx->buf = buf; |
ctx->buflen = len; |
return( 0 ); |
} |
void mbedtls_pem_free( mbedtls_pem_context *ctx ) |
{ |
if ( ctx->buf != NULL ) |
{ |
mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); |
mbedtls_free( ctx->buf ); |
} |
mbedtls_free( ctx->info ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); |
} |
#endif /* MBEDTLS_PEM_PARSE_C */ |
#if defined(MBEDTLS_PEM_WRITE_C) |
int mbedtls_pem_write_buffer( const char *header, const char *footer, |
const unsigned char *der_data, size_t der_len, |
unsigned char *buf, size_t buf_len, size_t *olen ) |
{ |
int ret; |
unsigned char *encode_buf = NULL, *c, *p = buf; |
size_t len = 0, use_len, add_len = 0; |
mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); |
add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; |
if( use_len + add_len > buf_len ) |
{ |
*olen = use_len + add_len; |
return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); |
} |
if( use_len != 0 && |
( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) |
return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); |
if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, |
der_len ) ) != 0 ) |
{ |
mbedtls_free( encode_buf ); |
return( ret ); |
} |
memcpy( p, header, strlen( header ) ); |
p += strlen( header ); |
c = encode_buf; |
while( use_len ) |
{ |
len = ( use_len > 64 ) ? 64 : use_len; |
memcpy( p, c, len ); |
use_len -= len; |
p += len; |
c += len; |
*p++ = '\n'; |
} |
memcpy( p, footer, strlen( footer ) ); |
p += strlen( footer ); |
*p++ = '\0'; |
*olen = p - buf; |
mbedtls_free( encode_buf ); |
return( 0 ); |
} |
#endif /* MBEDTLS_PEM_WRITE_C */ |
#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ |
/programs/develop/libraries/kos_mbedtls/library/pk.c |
---|
0,0 → 1,548 |
/* |
* Public Key abstraction layer |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PK_C) |
#include "mbedtls/pk.h" |
#include "mbedtls/pk_internal.h" |
#include "mbedtls/platform_util.h" |
#if defined(MBEDTLS_RSA_C) |
#include "mbedtls/rsa.h" |
#endif |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/ecp.h" |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
#include "mbedtls/ecdsa.h" |
#endif |
#include <limits.h> |
#include <stdint.h> |
/* Parameter validation macros based on platform_util.h */ |
#define PK_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) |
#define PK_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
/* |
* Initialise a mbedtls_pk_context |
*/ |
void mbedtls_pk_init( mbedtls_pk_context *ctx ) |
{ |
PK_VALIDATE( ctx != NULL ); |
ctx->pk_info = NULL; |
ctx->pk_ctx = NULL; |
} |
/* |
* Free (the components of) a mbedtls_pk_context |
*/ |
void mbedtls_pk_free( mbedtls_pk_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
if ( ctx->pk_info != NULL ) |
ctx->pk_info->ctx_free_func( ctx->pk_ctx ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); |
} |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* Initialize a restart context |
*/ |
void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) |
{ |
PK_VALIDATE( ctx != NULL ); |
ctx->pk_info = NULL; |
ctx->rs_ctx = NULL; |
} |
/* |
* Free the components of a restart context |
*/ |
void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) |
{ |
if( ctx == NULL || ctx->pk_info == NULL || |
ctx->pk_info->rs_free_func == NULL ) |
{ |
return; |
} |
ctx->pk_info->rs_free_func( ctx->rs_ctx ); |
ctx->pk_info = NULL; |
ctx->rs_ctx = NULL; |
} |
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
/* |
* Get pk_info structure from type |
*/ |
const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) |
{ |
switch( pk_type ) { |
#if defined(MBEDTLS_RSA_C) |
case MBEDTLS_PK_RSA: |
return( &mbedtls_rsa_info ); |
#endif |
#if defined(MBEDTLS_ECP_C) |
case MBEDTLS_PK_ECKEY: |
return( &mbedtls_eckey_info ); |
case MBEDTLS_PK_ECKEY_DH: |
return( &mbedtls_eckeydh_info ); |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
case MBEDTLS_PK_ECDSA: |
return( &mbedtls_ecdsa_info ); |
#endif |
/* MBEDTLS_PK_RSA_ALT omitted on purpose */ |
default: |
return( NULL ); |
} |
} |
/* |
* Initialise context |
*/ |
int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) |
{ |
PK_VALIDATE_RET( ctx != NULL ); |
if( info == NULL || ctx->pk_info != NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) |
return( MBEDTLS_ERR_PK_ALLOC_FAILED ); |
ctx->pk_info = info; |
return( 0 ); |
} |
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) |
/* |
* Initialize an RSA-alt context |
*/ |
int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, |
mbedtls_pk_rsa_alt_decrypt_func decrypt_func, |
mbedtls_pk_rsa_alt_sign_func sign_func, |
mbedtls_pk_rsa_alt_key_len_func key_len_func ) |
{ |
mbedtls_rsa_alt_context *rsa_alt; |
const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; |
PK_VALIDATE_RET( ctx != NULL ); |
if( ctx->pk_info != NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) |
return( MBEDTLS_ERR_PK_ALLOC_FAILED ); |
ctx->pk_info = info; |
rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; |
rsa_alt->key = key; |
rsa_alt->decrypt_func = decrypt_func; |
rsa_alt->sign_func = sign_func; |
rsa_alt->key_len_func = key_len_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ |
/* |
* Tell if a PK can do the operations of the given type |
*/ |
int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) |
{ |
/* A context with null pk_info is not set up yet and can't do anything. |
* For backward compatibility, also accept NULL instead of a context |
* pointer. */ |
if( ctx == NULL || ctx->pk_info == NULL ) |
return( 0 ); |
return( ctx->pk_info->can_do( type ) ); |
} |
/* |
* Helper for mbedtls_pk_sign and mbedtls_pk_verify |
*/ |
static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) |
{ |
const mbedtls_md_info_t *md_info; |
if( *hash_len != 0 ) |
return( 0 ); |
if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) |
return( -1 ); |
*hash_len = mbedtls_md_get_size( md_info ); |
return( 0 ); |
} |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* Helper to set up a restart context if needed |
*/ |
static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, |
const mbedtls_pk_info_t *info ) |
{ |
/* Don't do anything if already set up or invalid */ |
if( ctx == NULL || ctx->pk_info != NULL ) |
return( 0 ); |
/* Should never happen when we're called */ |
if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) |
return( MBEDTLS_ERR_PK_ALLOC_FAILED ); |
ctx->pk_info = info; |
return( 0 ); |
} |
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
/* |
* Verify a signature (restartable) |
*/ |
int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, |
mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len, |
mbedtls_pk_restart_ctx *rs_ctx ) |
{ |
PK_VALIDATE_RET( ctx != NULL ); |
PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || |
hash != NULL ); |
PK_VALIDATE_RET( sig != NULL ); |
if( ctx->pk_info == NULL || |
pk_hashlen_helper( md_alg, &hash_len ) != 0 ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* optimization: use non-restartable version if restart disabled */ |
if( rs_ctx != NULL && |
mbedtls_ecp_restart_is_enabled() && |
ctx->pk_info->verify_rs_func != NULL ) |
{ |
int ret; |
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) |
return( ret ); |
ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, |
md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); |
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) |
mbedtls_pk_restart_free( rs_ctx ); |
return( ret ); |
} |
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
(void) rs_ctx; |
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
if( ctx->pk_info->verify_func == NULL ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, |
sig, sig_len ) ); |
} |
/* |
* Verify a signature |
*/ |
int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len ) |
{ |
return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, |
sig, sig_len, NULL ) ); |
} |
/* |
* Verify a signature with options |
*/ |
int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, |
mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len ) |
{ |
PK_VALIDATE_RET( ctx != NULL ); |
PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || |
hash != NULL ); |
PK_VALIDATE_RET( sig != NULL ); |
if( ctx->pk_info == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
if( ! mbedtls_pk_can_do( ctx, type ) ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
if( type == MBEDTLS_PK_RSASSA_PSS ) |
{ |
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) |
int ret; |
const mbedtls_pk_rsassa_pss_options *pss_opts; |
#if SIZE_MAX > UINT_MAX |
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
#endif /* SIZE_MAX > UINT_MAX */ |
if( options == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; |
if( sig_len < mbedtls_pk_get_len( ctx ) ) |
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); |
ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), |
NULL, NULL, MBEDTLS_RSA_PUBLIC, |
md_alg, (unsigned int) hash_len, hash, |
pss_opts->mgf1_hash_id, |
pss_opts->expected_salt_len, |
sig ); |
if( ret != 0 ) |
return( ret ); |
if( sig_len > mbedtls_pk_get_len( ctx ) ) |
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); |
return( 0 ); |
#else |
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); |
#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ |
} |
/* General case: no options */ |
if( options != NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); |
} |
/* |
* Make a signature (restartable) |
*/ |
int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, |
mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
mbedtls_pk_restart_ctx *rs_ctx ) |
{ |
PK_VALIDATE_RET( ctx != NULL ); |
PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || |
hash != NULL ); |
PK_VALIDATE_RET( sig != NULL ); |
if( ctx->pk_info == NULL || |
pk_hashlen_helper( md_alg, &hash_len ) != 0 ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* optimization: use non-restartable version if restart disabled */ |
if( rs_ctx != NULL && |
mbedtls_ecp_restart_is_enabled() && |
ctx->pk_info->sign_rs_func != NULL ) |
{ |
int ret; |
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) |
return( ret ); |
ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, |
hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx ); |
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) |
mbedtls_pk_restart_free( rs_ctx ); |
return( ret ); |
} |
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
(void) rs_ctx; |
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
if( ctx->pk_info->sign_func == NULL ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, |
sig, sig_len, f_rng, p_rng ) ); |
} |
/* |
* Make a signature |
*/ |
int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, |
sig, sig_len, f_rng, p_rng, NULL ) ); |
} |
/* |
* Decrypt message |
*/ |
int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen, size_t osize, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
PK_VALIDATE_RET( ctx != NULL ); |
PK_VALIDATE_RET( input != NULL || ilen == 0 ); |
PK_VALIDATE_RET( output != NULL || osize == 0 ); |
PK_VALIDATE_RET( olen != NULL ); |
if( ctx->pk_info == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
if( ctx->pk_info->decrypt_func == NULL ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, |
output, olen, osize, f_rng, p_rng ) ); |
} |
/* |
* Encrypt message |
*/ |
int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen, size_t osize, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
PK_VALIDATE_RET( ctx != NULL ); |
PK_VALIDATE_RET( input != NULL || ilen == 0 ); |
PK_VALIDATE_RET( output != NULL || osize == 0 ); |
PK_VALIDATE_RET( olen != NULL ); |
if( ctx->pk_info == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
if( ctx->pk_info->encrypt_func == NULL ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, |
output, olen, osize, f_rng, p_rng ) ); |
} |
/* |
* Check public-private key pair |
*/ |
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) |
{ |
PK_VALIDATE_RET( pub != NULL ); |
PK_VALIDATE_RET( prv != NULL ); |
if( pub->pk_info == NULL || |
prv->pk_info == NULL || |
prv->pk_info->check_pair_func == NULL ) |
{ |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
} |
if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) |
{ |
if( pub->pk_info->type != MBEDTLS_PK_RSA ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
} |
else |
{ |
if( pub->pk_info != prv->pk_info ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
} |
return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); |
} |
/* |
* Get key size in bits |
*/ |
size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) |
{ |
/* For backward compatibility, accept NULL or a context that |
* isn't set up yet, and return a fake value that should be safe. */ |
if( ctx == NULL || ctx->pk_info == NULL ) |
return( 0 ); |
return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); |
} |
/* |
* Export debug information |
*/ |
int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) |
{ |
PK_VALIDATE_RET( ctx != NULL ); |
if( ctx->pk_info == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
if( ctx->pk_info->debug_func == NULL ) |
return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); |
ctx->pk_info->debug_func( ctx->pk_ctx, items ); |
return( 0 ); |
} |
/* |
* Access the PK type name |
*/ |
const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) |
{ |
if( ctx == NULL || ctx->pk_info == NULL ) |
return( "invalid PK" ); |
return( ctx->pk_info->name ); |
} |
/* |
* Access the PK type |
*/ |
mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) |
{ |
if( ctx == NULL || ctx->pk_info == NULL ) |
return( MBEDTLS_PK_NONE ); |
return( ctx->pk_info->type ); |
} |
#endif /* MBEDTLS_PK_C */ |
/programs/develop/libraries/kos_mbedtls/library/pk_wrap.c |
---|
0,0 → 1,721 |
/* |
* Public Key abstraction layer: wrapper functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PK_C) |
#include "mbedtls/pk_internal.h" |
/* Even if RSA not activated, for the sake of RSA-alt */ |
#include "mbedtls/rsa.h" |
#include <string.h> |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/ecp.h" |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
#include "mbedtls/ecdsa.h" |
#endif |
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) |
#include "mbedtls/platform_util.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include <limits.h> |
#include <stdint.h> |
#if defined(MBEDTLS_RSA_C) |
static int rsa_can_do( mbedtls_pk_type_t type ) |
{ |
return( type == MBEDTLS_PK_RSA || |
type == MBEDTLS_PK_RSASSA_PSS ); |
} |
static size_t rsa_get_bitlen( const void *ctx ) |
{ |
const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; |
return( 8 * mbedtls_rsa_get_len( rsa ) ); |
} |
static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len ) |
{ |
int ret; |
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; |
size_t rsa_len = mbedtls_rsa_get_len( rsa ); |
#if SIZE_MAX > UINT_MAX |
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
#endif /* SIZE_MAX > UINT_MAX */ |
if( sig_len < rsa_len ) |
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); |
if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, |
MBEDTLS_RSA_PUBLIC, md_alg, |
(unsigned int) hash_len, hash, sig ) ) != 0 ) |
return( ret ); |
/* The buffer contains a valid signature followed by extra data. |
* We have a special error code for that so that so that callers can |
* use mbedtls_pk_verify() to check "Does the buffer start with a |
* valid signature?" and not just "Does the buffer contain a valid |
* signature?". */ |
if( sig_len > rsa_len ) |
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); |
return( 0 ); |
} |
static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; |
#if SIZE_MAX > UINT_MAX |
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
#endif /* SIZE_MAX > UINT_MAX */ |
*sig_len = mbedtls_rsa_get_len( rsa ); |
return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, |
md_alg, (unsigned int) hash_len, hash, sig ) ); |
} |
static int rsa_decrypt_wrap( void *ctx, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen, size_t osize, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; |
if( ilen != mbedtls_rsa_get_len( rsa ) ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, |
MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); |
} |
static int rsa_encrypt_wrap( void *ctx, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen, size_t osize, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; |
*olen = mbedtls_rsa_get_len( rsa ); |
if( *olen > osize ) |
return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); |
return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, |
ilen, input, output ) ); |
} |
static int rsa_check_pair_wrap( const void *pub, const void *prv ) |
{ |
return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, |
(const mbedtls_rsa_context *) prv ) ); |
} |
static void *rsa_alloc_wrap( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); |
if( ctx != NULL ) |
mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); |
return( ctx ); |
} |
static void rsa_free_wrap( void *ctx ) |
{ |
mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); |
mbedtls_free( ctx ); |
} |
static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) |
{ |
items->type = MBEDTLS_PK_DEBUG_MPI; |
items->name = "rsa.N"; |
items->value = &( ((mbedtls_rsa_context *) ctx)->N ); |
items++; |
items->type = MBEDTLS_PK_DEBUG_MPI; |
items->name = "rsa.E"; |
items->value = &( ((mbedtls_rsa_context *) ctx)->E ); |
} |
const mbedtls_pk_info_t mbedtls_rsa_info = { |
MBEDTLS_PK_RSA, |
"RSA", |
rsa_get_bitlen, |
rsa_can_do, |
rsa_verify_wrap, |
rsa_sign_wrap, |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
NULL, |
NULL, |
#endif |
rsa_decrypt_wrap, |
rsa_encrypt_wrap, |
rsa_check_pair_wrap, |
rsa_alloc_wrap, |
rsa_free_wrap, |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
NULL, |
NULL, |
#endif |
rsa_debug, |
}; |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
/* |
* Generic EC key |
*/ |
static int eckey_can_do( mbedtls_pk_type_t type ) |
{ |
return( type == MBEDTLS_PK_ECKEY || |
type == MBEDTLS_PK_ECKEY_DH || |
type == MBEDTLS_PK_ECDSA ); |
} |
static size_t eckey_get_bitlen( const void *ctx ) |
{ |
return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); |
} |
#if defined(MBEDTLS_ECDSA_C) |
/* Forward declarations */ |
static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len ); |
static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); |
static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len ) |
{ |
int ret; |
mbedtls_ecdsa_context ecdsa; |
mbedtls_ecdsa_init( &ecdsa ); |
if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) |
ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); |
mbedtls_ecdsa_free( &ecdsa ); |
return( ret ); |
} |
static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
int ret; |
mbedtls_ecdsa_context ecdsa; |
mbedtls_ecdsa_init( &ecdsa ); |
if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) |
ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, |
f_rng, p_rng ); |
mbedtls_ecdsa_free( &ecdsa ); |
return( ret ); |
} |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
/* Forward declarations */ |
static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len, |
void *rs_ctx ); |
static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
void *rs_ctx ); |
/* |
* Restart context for ECDSA operations with ECKEY context |
* |
* We need to store an actual ECDSA context, as we need to pass the same to |
* the underlying ecdsa function, so we can't create it on the fly every time. |
*/ |
typedef struct |
{ |
mbedtls_ecdsa_restart_ctx ecdsa_rs; |
mbedtls_ecdsa_context ecdsa_ctx; |
} eckey_restart_ctx; |
static void *eckey_rs_alloc( void ) |
{ |
eckey_restart_ctx *rs_ctx; |
void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); |
if( ctx != NULL ) |
{ |
rs_ctx = ctx; |
mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); |
mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); |
} |
return( ctx ); |
} |
static void eckey_rs_free( void *ctx ) |
{ |
eckey_restart_ctx *rs_ctx; |
if( ctx == NULL) |
return; |
rs_ctx = ctx; |
mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); |
mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); |
mbedtls_free( ctx ); |
} |
static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len, |
void *rs_ctx ) |
{ |
int ret; |
eckey_restart_ctx *rs = rs_ctx; |
/* Should never happen */ |
if( rs == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
/* set up our own sub-context if needed (that is, on first run) */ |
if( rs->ecdsa_ctx.grp.pbits == 0 ) |
MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); |
MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, |
md_alg, hash, hash_len, |
sig, sig_len, &rs->ecdsa_rs ) ); |
cleanup: |
return( ret ); |
} |
static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
void *rs_ctx ) |
{ |
int ret; |
eckey_restart_ctx *rs = rs_ctx; |
/* Should never happen */ |
if( rs == NULL ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
/* set up our own sub-context if needed (that is, on first run) */ |
if( rs->ecdsa_ctx.grp.pbits == 0 ) |
MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); |
MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, |
hash, hash_len, sig, sig_len, |
f_rng, p_rng, &rs->ecdsa_rs ) ); |
cleanup: |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
#endif /* MBEDTLS_ECDSA_C */ |
static int eckey_check_pair( const void *pub, const void *prv ) |
{ |
return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, |
(const mbedtls_ecp_keypair *) prv ) ); |
} |
static void *eckey_alloc_wrap( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); |
if( ctx != NULL ) |
mbedtls_ecp_keypair_init( ctx ); |
return( ctx ); |
} |
static void eckey_free_wrap( void *ctx ) |
{ |
mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); |
mbedtls_free( ctx ); |
} |
static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) |
{ |
items->type = MBEDTLS_PK_DEBUG_ECP; |
items->name = "eckey.Q"; |
items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); |
} |
const mbedtls_pk_info_t mbedtls_eckey_info = { |
MBEDTLS_PK_ECKEY, |
"EC", |
eckey_get_bitlen, |
eckey_can_do, |
#if defined(MBEDTLS_ECDSA_C) |
eckey_verify_wrap, |
eckey_sign_wrap, |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
eckey_verify_rs_wrap, |
eckey_sign_rs_wrap, |
#endif |
#else /* MBEDTLS_ECDSA_C */ |
NULL, |
NULL, |
#endif /* MBEDTLS_ECDSA_C */ |
NULL, |
NULL, |
eckey_check_pair, |
eckey_alloc_wrap, |
eckey_free_wrap, |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
eckey_rs_alloc, |
eckey_rs_free, |
#endif |
eckey_debug, |
}; |
/* |
* EC key restricted to ECDH |
*/ |
static int eckeydh_can_do( mbedtls_pk_type_t type ) |
{ |
return( type == MBEDTLS_PK_ECKEY || |
type == MBEDTLS_PK_ECKEY_DH ); |
} |
const mbedtls_pk_info_t mbedtls_eckeydh_info = { |
MBEDTLS_PK_ECKEY_DH, |
"EC_DH", |
eckey_get_bitlen, /* Same underlying key structure */ |
eckeydh_can_do, |
NULL, |
NULL, |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
NULL, |
NULL, |
#endif |
NULL, |
NULL, |
eckey_check_pair, |
eckey_alloc_wrap, /* Same underlying key structure */ |
eckey_free_wrap, /* Same underlying key structure */ |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
NULL, |
NULL, |
#endif |
eckey_debug, /* Same underlying key structure */ |
}; |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_ECDSA_C) |
static int ecdsa_can_do( mbedtls_pk_type_t type ) |
{ |
return( type == MBEDTLS_PK_ECDSA ); |
} |
static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len ) |
{ |
int ret; |
((void) md_alg); |
ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, |
hash, hash_len, sig, sig_len ); |
if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) |
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); |
return( ret ); |
} |
static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, |
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); |
} |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
const unsigned char *sig, size_t sig_len, |
void *rs_ctx ) |
{ |
int ret; |
((void) md_alg); |
ret = mbedtls_ecdsa_read_signature_restartable( |
(mbedtls_ecdsa_context *) ctx, |
hash, hash_len, sig, sig_len, |
(mbedtls_ecdsa_restart_ctx *) rs_ctx ); |
if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) |
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); |
return( ret ); |
} |
static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
void *rs_ctx ) |
{ |
return( mbedtls_ecdsa_write_signature_restartable( |
(mbedtls_ecdsa_context *) ctx, |
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, |
(mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
static void *ecdsa_alloc_wrap( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); |
if( ctx != NULL ) |
mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); |
return( ctx ); |
} |
static void ecdsa_free_wrap( void *ctx ) |
{ |
mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); |
mbedtls_free( ctx ); |
} |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
static void *ecdsa_rs_alloc( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); |
if( ctx != NULL ) |
mbedtls_ecdsa_restart_init( ctx ); |
return( ctx ); |
} |
static void ecdsa_rs_free( void *ctx ) |
{ |
mbedtls_ecdsa_restart_free( ctx ); |
mbedtls_free( ctx ); |
} |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
const mbedtls_pk_info_t mbedtls_ecdsa_info = { |
MBEDTLS_PK_ECDSA, |
"ECDSA", |
eckey_get_bitlen, /* Compatible key structures */ |
ecdsa_can_do, |
ecdsa_verify_wrap, |
ecdsa_sign_wrap, |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
ecdsa_verify_rs_wrap, |
ecdsa_sign_rs_wrap, |
#endif |
NULL, |
NULL, |
eckey_check_pair, /* Compatible key structures */ |
ecdsa_alloc_wrap, |
ecdsa_free_wrap, |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
ecdsa_rs_alloc, |
ecdsa_rs_free, |
#endif |
eckey_debug, /* Compatible key structures */ |
}; |
#endif /* MBEDTLS_ECDSA_C */ |
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) |
/* |
* Support for alternative RSA-private implementations |
*/ |
static int rsa_alt_can_do( mbedtls_pk_type_t type ) |
{ |
return( type == MBEDTLS_PK_RSA ); |
} |
static size_t rsa_alt_get_bitlen( const void *ctx ) |
{ |
const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; |
return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); |
} |
static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, |
const unsigned char *hash, size_t hash_len, |
unsigned char *sig, size_t *sig_len, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; |
#if SIZE_MAX > UINT_MAX |
if( UINT_MAX < hash_len ) |
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
#endif /* SIZE_MAX > UINT_MAX */ |
*sig_len = rsa_alt->key_len_func( rsa_alt->key ); |
return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, |
md_alg, (unsigned int) hash_len, hash, sig ) ); |
} |
static int rsa_alt_decrypt_wrap( void *ctx, |
const unsigned char *input, size_t ilen, |
unsigned char *output, size_t *olen, size_t osize, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; |
((void) f_rng); |
((void) p_rng); |
if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
return( rsa_alt->decrypt_func( rsa_alt->key, |
MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); |
} |
#if defined(MBEDTLS_RSA_C) |
static int rsa_alt_check_pair( const void *pub, const void *prv ) |
{ |
unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; |
unsigned char hash[32]; |
size_t sig_len = 0; |
int ret; |
if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
memset( hash, 0x2a, sizeof( hash ) ); |
if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, |
hash, sizeof( hash ), |
sig, &sig_len, NULL, NULL ) ) != 0 ) |
{ |
return( ret ); |
} |
if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, |
hash, sizeof( hash ), sig, sig_len ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_RSA_C */ |
static void *rsa_alt_alloc_wrap( void ) |
{ |
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); |
if( ctx != NULL ) |
memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); |
return( ctx ); |
} |
static void rsa_alt_free_wrap( void *ctx ) |
{ |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); |
mbedtls_free( ctx ); |
} |
const mbedtls_pk_info_t mbedtls_rsa_alt_info = { |
MBEDTLS_PK_RSA_ALT, |
"RSA-alt", |
rsa_alt_get_bitlen, |
rsa_alt_can_do, |
NULL, |
rsa_alt_sign_wrap, |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
NULL, |
NULL, |
#endif |
rsa_alt_decrypt_wrap, |
NULL, |
#if defined(MBEDTLS_RSA_C) |
rsa_alt_check_pair, |
#else |
NULL, |
#endif |
rsa_alt_alloc_wrap, |
rsa_alt_free_wrap, |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
NULL, |
NULL, |
#endif |
NULL, |
}; |
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ |
#endif /* MBEDTLS_PK_C */ |
/programs/develop/libraries/kos_mbedtls/library/pkcs11.c |
---|
0,0 → 1,242 |
/** |
* \file pkcs11.c |
* |
* \brief Wrapper for PKCS#11 library libpkcs11-helper |
* |
* \author Adriaan de Jong <dejong@fox-it.com> |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#include "mbedtls/pkcs11.h" |
#if defined(MBEDTLS_PKCS11_C) |
#include "mbedtls/md.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/x509_crt.h" |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include <string.h> |
void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); |
} |
int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) |
{ |
int ret = 1; |
unsigned char *cert_blob = NULL; |
size_t cert_blob_size = 0; |
if( cert == NULL ) |
{ |
ret = 2; |
goto cleanup; |
} |
if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, |
&cert_blob_size ) != CKR_OK ) |
{ |
ret = 3; |
goto cleanup; |
} |
cert_blob = mbedtls_calloc( 1, cert_blob_size ); |
if( NULL == cert_blob ) |
{ |
ret = 4; |
goto cleanup; |
} |
if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, |
&cert_blob_size ) != CKR_OK ) |
{ |
ret = 5; |
goto cleanup; |
} |
if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) |
{ |
ret = 6; |
goto cleanup; |
} |
ret = 0; |
cleanup: |
if( NULL != cert_blob ) |
mbedtls_free( cert_blob ); |
return( ret ); |
} |
int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, |
pkcs11h_certificate_t pkcs11_cert ) |
{ |
int ret = 1; |
mbedtls_x509_crt cert; |
mbedtls_x509_crt_init( &cert ); |
if( priv_key == NULL ) |
goto cleanup; |
if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) |
goto cleanup; |
priv_key->len = mbedtls_pk_get_len( &cert.pk ); |
priv_key->pkcs11h_cert = pkcs11_cert; |
ret = 0; |
cleanup: |
mbedtls_x509_crt_free( &cert ); |
return( ret ); |
} |
void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) |
{ |
if( NULL != priv_key ) |
pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); |
} |
int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, |
int mode, size_t *olen, |
const unsigned char *input, |
unsigned char *output, |
size_t output_max_len ) |
{ |
size_t input_len, output_len; |
if( NULL == ctx ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( MBEDTLS_RSA_PRIVATE != mode ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
output_len = input_len = ctx->len; |
if( input_len < 16 || input_len > output_max_len ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* Determine size of output buffer */ |
if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, |
input_len, NULL, &output_len ) != CKR_OK ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
if( output_len > output_max_len ) |
return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); |
if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, |
input_len, output, &output_len ) != CKR_OK ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
*olen = output_len; |
return( 0 ); |
} |
int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
unsigned char *sig ) |
{ |
size_t sig_len = 0, asn_len = 0, oid_size = 0; |
unsigned char *p = sig; |
const char *oid; |
if( NULL == ctx ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( MBEDTLS_RSA_PRIVATE != mode ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( md_alg != MBEDTLS_MD_NONE ) |
{ |
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hashlen = mbedtls_md_get_size( md_info ); |
asn_len = 10 + oid_size; |
} |
sig_len = ctx->len; |
if( hashlen > sig_len || asn_len > sig_len || |
hashlen + asn_len > sig_len ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
if( md_alg != MBEDTLS_MD_NONE ) |
{ |
/* |
* DigestInfo ::= SEQUENCE { |
* digestAlgorithm DigestAlgorithmIdentifier, |
* digest Digest } |
* |
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier |
* |
* Digest ::= OCTET STRING |
*/ |
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; |
*p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); |
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; |
*p++ = (unsigned char) ( 0x04 + oid_size ); |
*p++ = MBEDTLS_ASN1_OID; |
*p++ = oid_size & 0xFF; |
memcpy( p, oid, oid_size ); |
p += oid_size; |
*p++ = MBEDTLS_ASN1_NULL; |
*p++ = 0x00; |
*p++ = MBEDTLS_ASN1_OCTET_STRING; |
*p++ = hashlen; |
} |
memcpy( p, hash, hashlen ); |
if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, |
asn_len + hashlen, sig, &sig_len ) != CKR_OK ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
return( 0 ); |
} |
#endif /* defined(MBEDTLS_PKCS11_C) */ |
/programs/develop/libraries/kos_mbedtls/library/pkcs12.c |
---|
0,0 → 1,367 |
/* |
* PKCS#12 Personal Information Exchange Syntax |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The PKCS #12 Personal Information Exchange Syntax Standard v1.1 |
* |
* http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf |
* ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PKCS12_C) |
#include "mbedtls/pkcs12.h" |
#include "mbedtls/asn1.h" |
#include "mbedtls/cipher.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_ARC4_C) |
#include "mbedtls/arc4.h" |
#endif |
#if defined(MBEDTLS_DES_C) |
#include "mbedtls/des.h" |
#endif |
#if defined(MBEDTLS_ASN1_PARSE_C) |
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, |
mbedtls_asn1_buf *salt, int *iterations ) |
{ |
int ret; |
unsigned char **p = ¶ms->p; |
const unsigned char *end = params->p + params->len; |
/* |
* pkcs-12PbeParams ::= SEQUENCE { |
* salt OCTET STRING, |
* iterations INTEGER |
* } |
* |
*/ |
if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) |
return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); |
salt->p = *p; |
*p += salt->len; |
if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) |
return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); |
if( *p != end ) |
return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
#define PKCS12_MAX_PWDLEN 128 |
static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, |
const unsigned char *pwd, size_t pwdlen, |
unsigned char *key, size_t keylen, |
unsigned char *iv, size_t ivlen ) |
{ |
int ret, iterations = 0; |
mbedtls_asn1_buf salt; |
size_t i; |
unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; |
if( pwdlen > PKCS12_MAX_PWDLEN ) |
return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); |
memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); |
memset( &unipwd, 0, sizeof(unipwd) ); |
if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, |
&iterations ) ) != 0 ) |
return( ret ); |
for( i = 0; i < pwdlen; i++ ) |
unipwd[i * 2 + 1] = pwd[i]; |
if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, |
salt.p, salt.len, md_type, |
MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) |
{ |
return( ret ); |
} |
if( iv == NULL || ivlen == 0 ) |
return( 0 ); |
if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, |
salt.p, salt.len, md_type, |
MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
#undef PKCS12_MAX_PWDLEN |
int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, |
const unsigned char *pwd, size_t pwdlen, |
const unsigned char *data, size_t len, |
unsigned char *output ) |
{ |
#if !defined(MBEDTLS_ARC4_C) |
((void) pbe_params); |
((void) mode); |
((void) pwd); |
((void) pwdlen); |
((void) data); |
((void) len); |
((void) output); |
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); |
#else |
int ret; |
unsigned char key[16]; |
mbedtls_arc4_context ctx; |
((void) mode); |
mbedtls_arc4_init( &ctx ); |
if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, |
pwd, pwdlen, |
key, 16, NULL, 0 ) ) != 0 ) |
{ |
return( ret ); |
} |
mbedtls_arc4_setup( &ctx, key, 16 ); |
if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_platform_zeroize( key, sizeof( key ) ); |
mbedtls_arc4_free( &ctx ); |
return( ret ); |
#endif /* MBEDTLS_ARC4_C */ |
} |
int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, |
mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, |
const unsigned char *pwd, size_t pwdlen, |
const unsigned char *data, size_t len, |
unsigned char *output ) |
{ |
int ret, keylen = 0; |
unsigned char key[32]; |
unsigned char iv[16]; |
const mbedtls_cipher_info_t *cipher_info; |
mbedtls_cipher_context_t cipher_ctx; |
size_t olen = 0; |
cipher_info = mbedtls_cipher_info_from_type( cipher_type ); |
if( cipher_info == NULL ) |
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); |
keylen = cipher_info->key_bitlen / 8; |
if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, |
key, keylen, |
iv, cipher_info->iv_size ) ) != 0 ) |
{ |
return( ret ); |
} |
mbedtls_cipher_init( &cipher_ctx ); |
if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, |
output, &olen ) ) != 0 ) |
{ |
goto exit; |
} |
if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) |
ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; |
exit: |
mbedtls_platform_zeroize( key, sizeof( key ) ); |
mbedtls_platform_zeroize( iv, sizeof( iv ) ); |
mbedtls_cipher_free( &cipher_ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_ASN1_PARSE_C */ |
static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, |
const unsigned char *filler, size_t fill_len ) |
{ |
unsigned char *p = data; |
size_t use_len; |
while( data_len > 0 ) |
{ |
use_len = ( data_len > fill_len ) ? fill_len : data_len; |
memcpy( p, filler, use_len ); |
p += use_len; |
data_len -= use_len; |
} |
} |
int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, |
const unsigned char *pwd, size_t pwdlen, |
const unsigned char *salt, size_t saltlen, |
mbedtls_md_type_t md_type, int id, int iterations ) |
{ |
int ret; |
unsigned int j; |
unsigned char diversifier[128]; |
unsigned char salt_block[128], pwd_block[128], hash_block[128]; |
unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; |
unsigned char *p; |
unsigned char c; |
size_t hlen, use_len, v, i; |
const mbedtls_md_info_t *md_info; |
mbedtls_md_context_t md_ctx; |
// This version only allows max of 64 bytes of password or salt |
if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) |
return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); |
md_info = mbedtls_md_info_from_type( md_type ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); |
mbedtls_md_init( &md_ctx ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) |
return( ret ); |
hlen = mbedtls_md_get_size( md_info ); |
if( hlen <= 32 ) |
v = 64; |
else |
v = 128; |
memset( diversifier, (unsigned char) id, v ); |
pkcs12_fill_buffer( salt_block, v, salt, saltlen ); |
pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); |
p = data; |
while( datalen > 0 ) |
{ |
// Calculate hash( diversifier || salt_block || pwd_block ) |
if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) |
goto exit; |
// Perform remaining ( iterations - 1 ) recursive hash calculations |
for( i = 1; i < (size_t) iterations; i++ ) |
{ |
if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) |
goto exit; |
} |
use_len = ( datalen > hlen ) ? hlen : datalen; |
memcpy( p, hash_output, use_len ); |
datalen -= use_len; |
p += use_len; |
if( datalen == 0 ) |
break; |
// Concatenating copies of hash_output into hash_block (B) |
pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); |
// B += 1 |
for( i = v; i > 0; i-- ) |
if( ++hash_block[i - 1] != 0 ) |
break; |
// salt_block += B |
c = 0; |
for( i = v; i > 0; i-- ) |
{ |
j = salt_block[i - 1] + hash_block[i - 1] + c; |
c = (unsigned char) (j >> 8); |
salt_block[i - 1] = j & 0xFF; |
} |
// pwd_block += B |
c = 0; |
for( i = v; i > 0; i-- ) |
{ |
j = pwd_block[i - 1] + hash_block[i - 1] + c; |
c = (unsigned char) (j >> 8); |
pwd_block[i - 1] = j & 0xFF; |
} |
} |
ret = 0; |
exit: |
mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); |
mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); |
mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); |
mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); |
mbedtls_md_free( &md_ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_PKCS12_C */ |
/programs/develop/libraries/kos_mbedtls/library/pkcs5.c |
---|
0,0 → 1,413 |
/** |
* \file pkcs5.c |
* |
* \brief PKCS#5 functions |
* |
* \author Mathias Olsson <mathias@kompetensum.com> |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* PKCS#5 includes PBKDF2 and more |
* |
* http://tools.ietf.org/html/rfc2898 (Specification) |
* http://tools.ietf.org/html/rfc6070 (Test vectors) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PKCS5_C) |
#include "mbedtls/pkcs5.h" |
#if defined(MBEDTLS_ASN1_PARSE_C) |
#include "mbedtls/asn1.h" |
#include "mbedtls/cipher.h" |
#include "mbedtls/oid.h" |
#endif /* MBEDTLS_ASN1_PARSE_C */ |
#include <string.h> |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif |
#if defined(MBEDTLS_ASN1_PARSE_C) |
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, |
mbedtls_asn1_buf *salt, int *iterations, |
int *keylen, mbedtls_md_type_t *md_type ) |
{ |
int ret; |
mbedtls_asn1_buf prf_alg_oid; |
unsigned char *p = params->p; |
const unsigned char *end = params->p + params->len; |
if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
/* |
* PBKDF2-params ::= SEQUENCE { |
* salt OCTET STRING, |
* iterationCount INTEGER, |
* keyLength INTEGER OPTIONAL |
* prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 |
* } |
* |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); |
salt->p = p; |
p += salt->len; |
if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); |
if( p == end ) |
return( 0 ); |
if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) |
{ |
if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); |
} |
if( p == end ) |
return( 0 ); |
if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); |
if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) |
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); |
if( p != end ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, |
const unsigned char *pwd, size_t pwdlen, |
const unsigned char *data, size_t datalen, |
unsigned char *output ) |
{ |
int ret, iterations = 0, keylen = 0; |
unsigned char *p, *end; |
mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; |
mbedtls_asn1_buf salt; |
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; |
unsigned char key[32], iv[32]; |
size_t olen = 0; |
const mbedtls_md_info_t *md_info; |
const mbedtls_cipher_info_t *cipher_info; |
mbedtls_md_context_t md_ctx; |
mbedtls_cipher_type_t cipher_alg; |
mbedtls_cipher_context_t cipher_ctx; |
p = pbe_params->p; |
end = p + pbe_params->len; |
/* |
* PBES2-params ::= SEQUENCE { |
* keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, |
* encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} |
* } |
*/ |
if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); |
// Only PBKDF2 supported at the moment |
// |
if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) |
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); |
if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, |
&salt, &iterations, &keylen, |
&md_type ) ) != 0 ) |
{ |
return( ret ); |
} |
md_info = mbedtls_md_info_from_type( md_type ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); |
if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, |
&enc_scheme_params ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); |
} |
if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) |
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); |
cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); |
if( cipher_info == NULL ) |
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); |
/* |
* The value of keylen from pkcs5_parse_pbkdf2_params() is ignored |
* since it is optional and we don't know if it was set or not |
*/ |
keylen = cipher_info->key_bitlen / 8; |
if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || |
enc_scheme_params.len != cipher_info->iv_size ) |
{ |
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); |
} |
mbedtls_md_init( &md_ctx ); |
mbedtls_cipher_init( &cipher_ctx ); |
memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, |
iterations, keylen, key ) ) != 0 ) |
{ |
goto exit; |
} |
if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, |
data, datalen, output, &olen ) ) != 0 ) |
ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; |
exit: |
mbedtls_md_free( &md_ctx ); |
mbedtls_cipher_free( &cipher_ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_ASN1_PARSE_C */ |
int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, |
size_t plen, const unsigned char *salt, size_t slen, |
unsigned int iteration_count, |
uint32_t key_length, unsigned char *output ) |
{ |
int ret, j; |
unsigned int i; |
unsigned char md1[MBEDTLS_MD_MAX_SIZE]; |
unsigned char work[MBEDTLS_MD_MAX_SIZE]; |
unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); |
size_t use_len; |
unsigned char *out_p = output; |
unsigned char counter[4]; |
memset( counter, 0, 4 ); |
counter[3] = 1; |
#if UINT_MAX > 0xFFFFFFFF |
if( iteration_count > 0xFFFFFFFF ) |
return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); |
#endif |
while( key_length ) |
{ |
// U1 ends up in work |
// |
if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) |
return( ret ); |
memcpy( md1, work, md_size ); |
for( i = 1; i < iteration_count; i++ ) |
{ |
// U2 ends up in md1 |
// |
if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) |
return( ret ); |
// U1 xor U2 |
// |
for( j = 0; j < md_size; j++ ) |
work[j] ^= md1[j]; |
} |
use_len = ( key_length < md_size ) ? key_length : md_size; |
memcpy( out_p, work, use_len ); |
key_length -= (uint32_t) use_len; |
out_p += use_len; |
for( i = 4; i > 0; i-- ) |
if( ++counter[i - 1] != 0 ) |
break; |
} |
return( 0 ); |
} |
#if defined(MBEDTLS_SELF_TEST) |
#if !defined(MBEDTLS_SHA1_C) |
int mbedtls_pkcs5_self_test( int verbose ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); |
return( 0 ); |
} |
#else |
#define MAX_TESTS 6 |
static const size_t plen[MAX_TESTS] = |
{ 8, 8, 8, 24, 9 }; |
static const unsigned char password[MAX_TESTS][32] = |
{ |
"password", |
"password", |
"password", |
"passwordPASSWORDpassword", |
"pass\0word", |
}; |
static const size_t slen[MAX_TESTS] = |
{ 4, 4, 4, 36, 5 }; |
static const unsigned char salt[MAX_TESTS][40] = |
{ |
"salt", |
"salt", |
"salt", |
"saltSALTsaltSALTsaltSALTsaltSALTsalt", |
"sa\0lt", |
}; |
static const uint32_t it_cnt[MAX_TESTS] = |
{ 1, 2, 4096, 4096, 4096 }; |
static const uint32_t key_len[MAX_TESTS] = |
{ 20, 20, 20, 25, 16 }; |
static const unsigned char result_key[MAX_TESTS][32] = |
{ |
{ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, |
0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, |
0x2f, 0xe0, 0x37, 0xa6 }, |
{ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, |
0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, |
0xd8, 0xde, 0x89, 0x57 }, |
{ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, |
0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, |
0x65, 0xa4, 0x29, 0xc1 }, |
{ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, |
0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, |
0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, |
0x38 }, |
{ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, |
0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, |
}; |
int mbedtls_pkcs5_self_test( int verbose ) |
{ |
mbedtls_md_context_t sha1_ctx; |
const mbedtls_md_info_t *info_sha1; |
int ret, i; |
unsigned char key[64]; |
mbedtls_md_init( &sha1_ctx ); |
info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); |
if( info_sha1 == NULL ) |
{ |
ret = 1; |
goto exit; |
} |
if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) |
{ |
ret = 1; |
goto exit; |
} |
for( i = 0; i < MAX_TESTS; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); |
ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], |
slen[i], it_cnt[i], key_len[i], key ); |
if( ret != 0 || |
memcmp( result_key[i], key, key_len[i] ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
exit: |
mbedtls_md_free( &sha1_ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_PKCS5_C */ |
/programs/develop/libraries/kos_mbedtls/library/pkparse.c |
---|
0,0 → 1,1540 |
/* |
* Public Key layer for parsing key files and structures |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PK_PARSE_C) |
#include "mbedtls/pk.h" |
#include "mbedtls/asn1.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_RSA_C) |
#include "mbedtls/rsa.h" |
#endif |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/ecp.h" |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
#include "mbedtls/ecdsa.h" |
#endif |
#if defined(MBEDTLS_PEM_PARSE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_PKCS5_C) |
#include "mbedtls/pkcs5.h" |
#endif |
#if defined(MBEDTLS_PKCS12_C) |
#include "mbedtls/pkcs12.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
/* Parameter validation macros based on platform_util.h */ |
#define PK_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) |
#define PK_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if defined(MBEDTLS_FS_IO) |
/* |
* Load all data from a file into a given buffer. |
* |
* The file is expected to contain either PEM or DER encoded data. |
* A terminating null byte is always appended. It is included in the announced |
* length only if the data looks like it is PEM encoded. |
*/ |
int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) |
{ |
FILE *f; |
long size; |
PK_VALIDATE_RET( path != NULL ); |
PK_VALIDATE_RET( buf != NULL ); |
PK_VALIDATE_RET( n != NULL ); |
if( ( f = fopen( path, "rb" ) ) == NULL ) |
return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); |
fseek( f, 0, SEEK_END ); |
if( ( size = ftell( f ) ) == -1 ) |
{ |
fclose( f ); |
return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); |
} |
fseek( f, 0, SEEK_SET ); |
*n = (size_t) size; |
if( *n + 1 == 0 || |
( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) |
{ |
fclose( f ); |
return( MBEDTLS_ERR_PK_ALLOC_FAILED ); |
} |
if( fread( *buf, 1, *n, f ) != *n ) |
{ |
fclose( f ); |
mbedtls_platform_zeroize( *buf, *n ); |
mbedtls_free( *buf ); |
return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); |
} |
fclose( f ); |
(*buf)[*n] = '\0'; |
if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) |
++*n; |
return( 0 ); |
} |
/* |
* Load and parse a private key |
*/ |
int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, |
const char *path, const char *pwd ) |
{ |
int ret; |
size_t n; |
unsigned char *buf; |
PK_VALIDATE_RET( ctx != NULL ); |
PK_VALIDATE_RET( path != NULL ); |
if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) |
return( ret ); |
if( pwd == NULL ) |
ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); |
else |
ret = mbedtls_pk_parse_key( ctx, buf, n, |
(const unsigned char *) pwd, strlen( pwd ) ); |
mbedtls_platform_zeroize( buf, n ); |
mbedtls_free( buf ); |
return( ret ); |
} |
/* |
* Load and parse a public key |
*/ |
int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) |
{ |
int ret; |
size_t n; |
unsigned char *buf; |
PK_VALIDATE_RET( ctx != NULL ); |
PK_VALIDATE_RET( path != NULL ); |
if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) |
return( ret ); |
ret = mbedtls_pk_parse_public_key( ctx, buf, n ); |
mbedtls_platform_zeroize( buf, n ); |
mbedtls_free( buf ); |
return( ret ); |
} |
#endif /* MBEDTLS_FS_IO */ |
#if defined(MBEDTLS_ECP_C) |
/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf |
* |
* ECParameters ::= CHOICE { |
* namedCurve OBJECT IDENTIFIER |
* specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } |
* -- implicitCurve NULL |
* } |
*/ |
static int pk_get_ecparams( unsigned char **p, const unsigned char *end, |
mbedtls_asn1_buf *params ) |
{ |
int ret; |
if ( end - *p < 1 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
/* Tag may be either OID or SEQUENCE */ |
params->tag = **p; |
if( params->tag != MBEDTLS_ASN1_OID |
#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) |
&& params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) |
#endif |
) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
} |
if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
params->p = *p; |
*p += params->len; |
if( *p != end ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) |
/* |
* Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. |
* WARNING: the resulting group should only be used with |
* pk_group_id_from_specified(), since its base point may not be set correctly |
* if it was encoded compressed. |
* |
* SpecifiedECDomain ::= SEQUENCE { |
* version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), |
* fieldID FieldID {{FieldTypes}}, |
* curve Curve, |
* base ECPoint, |
* order INTEGER, |
* cofactor INTEGER OPTIONAL, |
* hash HashAlgorithm OPTIONAL, |
* ... |
* } |
* |
* We only support prime-field as field type, and ignore hash and cofactor. |
*/ |
static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) |
{ |
int ret; |
unsigned char *p = params->p; |
const unsigned char * const end = params->p + params->len; |
const unsigned char *end_field, *end_curve; |
size_t len; |
int ver; |
/* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ |
if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( ver < 1 || ver > 3 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
/* |
* FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field |
* fieldType FIELD-ID.&id({IOSet}), |
* parameters FIELD-ID.&Type({IOSet}{@fieldType}) |
* } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( ret ); |
end_field = p + len; |
/* |
* FIELD-ID ::= TYPE-IDENTIFIER |
* FieldTypes FIELD-ID ::= { |
* { Prime-p IDENTIFIED BY prime-field } | |
* { Characteristic-two IDENTIFIED BY characteristic-two-field } |
* } |
* prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) |
return( ret ); |
if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || |
memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); |
} |
p += len; |
/* Prime-p ::= INTEGER -- Field of size p. */ |
if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
grp->pbits = mbedtls_mpi_bitlen( &grp->P ); |
if( p != end_field ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
/* |
* Curve ::= SEQUENCE { |
* a FieldElement, |
* b FieldElement, |
* seed BIT STRING OPTIONAL |
* -- Shall be present if used in SpecifiedECDomain |
* -- with version equal to ecdpVer2 or ecdpVer3 |
* } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( ret ); |
end_curve = p + len; |
/* |
* FieldElement ::= OCTET STRING |
* containing an integer in the case of a prime field |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || |
( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
p += len; |
if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || |
( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
p += len; |
/* Ignore seed BIT STRING OPTIONAL */ |
if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) |
p += len; |
if( p != end_curve ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
/* |
* ECPoint ::= OCTET STRING |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, |
( const unsigned char *) p, len ) ) != 0 ) |
{ |
/* |
* If we can't read the point because it's compressed, cheat by |
* reading only the X coordinate and the parity bit of Y. |
*/ |
if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || |
( p[0] != 0x02 && p[0] != 0x03 ) || |
len != mbedtls_mpi_size( &grp->P ) + 1 || |
mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || |
mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || |
mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
} |
} |
p += len; |
/* |
* order INTEGER |
*/ |
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
grp->nbits = mbedtls_mpi_bitlen( &grp->N ); |
/* |
* Allow optional elements by purposefully not enforcing p == end here. |
*/ |
return( 0 ); |
} |
/* |
* Find the group id associated with an (almost filled) group as generated by |
* pk_group_from_specified(), or return an error if unknown. |
*/ |
static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) |
{ |
int ret = 0; |
mbedtls_ecp_group ref; |
const mbedtls_ecp_group_id *id; |
mbedtls_ecp_group_init( &ref ); |
for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) |
{ |
/* Load the group associated to that id */ |
mbedtls_ecp_group_free( &ref ); |
MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); |
/* Compare to the group we were given, starting with easy tests */ |
if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && |
mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && |
mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && |
mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && |
mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && |
mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && |
mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && |
/* For Y we may only know the parity bit, so compare only that */ |
mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) |
{ |
break; |
} |
} |
cleanup: |
mbedtls_ecp_group_free( &ref ); |
*grp_id = *id; |
if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) |
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; |
return( ret ); |
} |
/* |
* Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID |
*/ |
static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, |
mbedtls_ecp_group_id *grp_id ) |
{ |
int ret; |
mbedtls_ecp_group grp; |
mbedtls_ecp_group_init( &grp ); |
if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) |
goto cleanup; |
ret = pk_group_id_from_group( &grp, grp_id ); |
cleanup: |
mbedtls_ecp_group_free( &grp ); |
return( ret ); |
} |
#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ |
/* |
* Use EC parameters to initialise an EC group |
* |
* ECParameters ::= CHOICE { |
* namedCurve OBJECT IDENTIFIER |
* specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } |
* -- implicitCurve NULL |
*/ |
static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) |
{ |
int ret; |
mbedtls_ecp_group_id grp_id; |
if( params->tag == MBEDTLS_ASN1_OID ) |
{ |
if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) |
return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); |
} |
else |
{ |
#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) |
if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) |
return( ret ); |
#else |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
#endif |
} |
/* |
* grp may already be initilialized; if so, make sure IDs match |
*/ |
if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
/* |
* EC public key is an EC point |
* |
* The caller is responsible for clearing the structure upon failure if |
* desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE |
* return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. |
*/ |
static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, |
mbedtls_ecp_keypair *key ) |
{ |
int ret; |
if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, |
(const unsigned char *) *p, end - *p ) ) == 0 ) |
{ |
ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); |
} |
/* |
* We know mbedtls_ecp_point_read_binary consumed all bytes or failed |
*/ |
*p = (unsigned char *) end; |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_RSA_C) |
/* |
* RSAPublicKey ::= SEQUENCE { |
* modulus INTEGER, -- n |
* publicExponent INTEGER -- e |
* } |
*/ |
static int pk_get_rsapubkey( unsigned char **p, |
const unsigned char *end, |
mbedtls_rsa_context *rsa ) |
{ |
int ret; |
size_t len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); |
if( *p + len != end ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
/* Import N */ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); |
if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, |
NULL, 0, NULL, 0 ) ) != 0 ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); |
*p += len; |
/* Import E */ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); |
if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, |
NULL, 0, *p, len ) ) != 0 ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); |
*p += len; |
if( mbedtls_rsa_complete( rsa ) != 0 || |
mbedtls_rsa_check_pubkey( rsa ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); |
} |
if( *p != end ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
#endif /* MBEDTLS_RSA_C */ |
/* Get a PK algorithm identifier |
* |
* AlgorithmIdentifier ::= SEQUENCE { |
* algorithm OBJECT IDENTIFIER, |
* parameters ANY DEFINED BY algorithm OPTIONAL } |
*/ |
static int pk_get_pk_alg( unsigned char **p, |
const unsigned char *end, |
mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) |
{ |
int ret; |
mbedtls_asn1_buf alg_oid; |
memset( params, 0, sizeof(mbedtls_asn1_buf) ); |
if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) |
return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); |
if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) |
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
/* |
* No parameters with RSA (only for EC) |
*/ |
if( *pk_alg == MBEDTLS_PK_RSA && |
( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || |
params->len != 0 ) ) |
{ |
return( MBEDTLS_ERR_PK_INVALID_ALG ); |
} |
return( 0 ); |
} |
/* |
* SubjectPublicKeyInfo ::= SEQUENCE { |
* algorithm AlgorithmIdentifier, |
* subjectPublicKey BIT STRING } |
*/ |
int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, |
mbedtls_pk_context *pk ) |
{ |
int ret; |
size_t len; |
mbedtls_asn1_buf alg_params; |
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; |
const mbedtls_pk_info_t *pk_info; |
PK_VALIDATE_RET( p != NULL ); |
PK_VALIDATE_RET( *p != NULL ); |
PK_VALIDATE_RET( end != NULL ); |
PK_VALIDATE_RET( pk != NULL ); |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
end = *p + len; |
if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); |
if( *p + len != end ) |
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) |
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) |
return( ret ); |
#if defined(MBEDTLS_RSA_C) |
if( pk_alg == MBEDTLS_PK_RSA ) |
{ |
ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); |
} else |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) |
{ |
ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); |
if( ret == 0 ) |
ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); |
} else |
#endif /* MBEDTLS_ECP_C */ |
ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; |
if( ret == 0 && *p != end ) |
ret = MBEDTLS_ERR_PK_INVALID_PUBKEY |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; |
if( ret != 0 ) |
mbedtls_pk_free( pk ); |
return( ret ); |
} |
#if defined(MBEDTLS_RSA_C) |
/* |
* Wrapper around mbedtls_asn1_get_mpi() that rejects zero. |
* |
* The value zero is: |
* - never a valid value for an RSA parameter |
* - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). |
* |
* Since values can't be omitted in PKCS#1, passing a zero value to |
* rsa_complete() would be incorrect, so reject zero values early. |
*/ |
static int asn1_get_nonzero_mpi( unsigned char **p, |
const unsigned char *end, |
mbedtls_mpi *X ) |
{ |
int ret; |
ret = mbedtls_asn1_get_mpi( p, end, X ); |
if( ret != 0 ) |
return( ret ); |
if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
return( 0 ); |
} |
/* |
* Parse a PKCS#1 encoded private RSA key |
*/ |
static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, |
const unsigned char *key, |
size_t keylen ) |
{ |
int ret, version; |
size_t len; |
unsigned char *p, *end; |
mbedtls_mpi T; |
mbedtls_mpi_init( &T ); |
p = (unsigned char *) key; |
end = p + keylen; |
/* |
* This function parses the RSAPrivateKey (PKCS#1) |
* |
* RSAPrivateKey ::= SEQUENCE { |
* version Version, |
* modulus INTEGER, -- n |
* publicExponent INTEGER, -- e |
* privateExponent INTEGER, -- d |
* prime1 INTEGER, -- p |
* prime2 INTEGER, -- q |
* exponent1 INTEGER, -- d mod (p-1) |
* exponent2 INTEGER, -- d mod (q-1) |
* coefficient INTEGER, -- (inverse of q) mod p |
* otherPrimeInfos OtherPrimeInfos OPTIONAL |
* } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
end = p + len; |
if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
if( version != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); |
} |
/* Import N */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, |
NULL, NULL ) ) != 0 ) |
goto cleanup; |
/* Import E */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, |
NULL, &T ) ) != 0 ) |
goto cleanup; |
/* Import D */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, |
&T, NULL ) ) != 0 ) |
goto cleanup; |
/* Import P */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, |
NULL, NULL ) ) != 0 ) |
goto cleanup; |
/* Import Q */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, |
NULL, NULL ) ) != 0 ) |
goto cleanup; |
#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) |
/* |
* The RSA CRT parameters DP, DQ and QP are nominally redundant, in |
* that they can be easily recomputed from D, P and Q. However by |
* parsing them from the PKCS1 structure it is possible to avoid |
* recalculating them which both reduces the overhead of loading |
* RSA private keys into memory and also avoids side channels which |
* can arise when computing those values, since all of D, P, and Q |
* are secret. See https://eprint.iacr.org/2020/055 for a |
* description of one such attack. |
*/ |
/* Import DP */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) |
goto cleanup; |
/* Import DQ */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) |
goto cleanup; |
/* Import QP */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) |
goto cleanup; |
#else |
/* Verify existance of the CRT params */ |
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || |
( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) |
goto cleanup; |
#endif |
/* rsa_complete() doesn't complete anything with the default |
* implementation but is still called: |
* - for the benefit of alternative implementation that may want to |
* pre-compute stuff beyond what's provided (eg Montgomery factors) |
* - as is also sanity-checks the key |
* |
* Furthermore, we also check the public part for consistency with |
* mbedtls_pk_parse_pubkey(), as it includes size minima for example. |
*/ |
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || |
( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) |
{ |
goto cleanup; |
} |
if( p != end ) |
{ |
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ; |
} |
cleanup: |
mbedtls_mpi_free( &T ); |
if( ret != 0 ) |
{ |
/* Wrap error code if it's coming from a lower level */ |
if( ( ret & 0xff80 ) == 0 ) |
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret; |
else |
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; |
mbedtls_rsa_free( rsa ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
/* |
* Parse a SEC1 encoded private EC key |
*/ |
static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, |
const unsigned char *key, |
size_t keylen ) |
{ |
int ret; |
int version, pubkey_done; |
size_t len; |
mbedtls_asn1_buf params; |
unsigned char *p = (unsigned char *) key; |
unsigned char *end = p + keylen; |
unsigned char *end2; |
/* |
* RFC 5915, or SEC1 Appendix C.4 |
* |
* ECPrivateKey ::= SEQUENCE { |
* version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), |
* privateKey OCTET STRING, |
* parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, |
* publicKey [1] BIT STRING OPTIONAL |
* } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
end = p + len; |
if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( version != 1 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) |
{ |
mbedtls_ecp_keypair_free( eck ); |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
p += len; |
pubkey_done = 0; |
if( p != end ) |
{ |
/* |
* Is 'parameters' present? |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) |
{ |
if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || |
( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) |
{ |
mbedtls_ecp_keypair_free( eck ); |
return( ret ); |
} |
} |
else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
{ |
mbedtls_ecp_keypair_free( eck ); |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
} |
if( p != end ) |
{ |
/* |
* Is 'publickey' present? If not, or if we can't read it (eg because it |
* is compressed), create it from the private key. |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) |
{ |
end2 = p + len; |
if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( p + len != end2 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) |
pubkey_done = 1; |
else |
{ |
/* |
* The only acceptable failure mode of pk_get_ecpubkey() above |
* is if the point format is not recognized. |
*/ |
if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
} |
} |
else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
{ |
mbedtls_ecp_keypair_free( eck ); |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
} |
if( ! pubkey_done && |
( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, |
NULL, NULL ) ) != 0 ) |
{ |
mbedtls_ecp_keypair_free( eck ); |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) |
{ |
mbedtls_ecp_keypair_free( eck ); |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_ECP_C */ |
/* |
* Parse an unencrypted PKCS#8 encoded private key |
* |
* Notes: |
* |
* - This function does not own the key buffer. It is the |
* responsibility of the caller to take care of zeroizing |
* and freeing it after use. |
* |
* - The function is responsible for freeing the provided |
* PK context on failure. |
* |
*/ |
static int pk_parse_key_pkcs8_unencrypted_der( |
mbedtls_pk_context *pk, |
const unsigned char* key, |
size_t keylen ) |
{ |
int ret, version; |
size_t len; |
mbedtls_asn1_buf params; |
unsigned char *p = (unsigned char *) key; |
unsigned char *end = p + keylen; |
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; |
const mbedtls_pk_info_t *pk_info; |
/* |
* This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) |
* |
* PrivateKeyInfo ::= SEQUENCE { |
* version Version, |
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, |
* privateKey PrivateKey, |
* attributes [0] IMPLICIT Attributes OPTIONAL } |
* |
* Version ::= INTEGER |
* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier |
* PrivateKey ::= OCTET STRING |
* |
* The PrivateKey OCTET STRING is a SEC1 ECPrivateKey |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
end = p + len; |
if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( version != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); |
if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( len < 1 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) |
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) |
return( ret ); |
#if defined(MBEDTLS_RSA_C) |
if( pk_alg == MBEDTLS_PK_RSA ) |
{ |
if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) |
{ |
mbedtls_pk_free( pk ); |
return( ret ); |
} |
} else |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) |
{ |
if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || |
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) |
{ |
mbedtls_pk_free( pk ); |
return( ret ); |
} |
} else |
#endif /* MBEDTLS_ECP_C */ |
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
return( 0 ); |
} |
/* |
* Parse an encrypted PKCS#8 encoded private key |
* |
* To save space, the decryption happens in-place on the given key buffer. |
* Also, while this function may modify the keybuffer, it doesn't own it, |
* and instead it is the responsibility of the caller to zeroize and properly |
* free it after use. |
* |
*/ |
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) |
static int pk_parse_key_pkcs8_encrypted_der( |
mbedtls_pk_context *pk, |
unsigned char *key, size_t keylen, |
const unsigned char *pwd, size_t pwdlen ) |
{ |
int ret, decrypted = 0; |
size_t len; |
unsigned char *buf; |
unsigned char *p, *end; |
mbedtls_asn1_buf pbe_alg_oid, pbe_params; |
#if defined(MBEDTLS_PKCS12_C) |
mbedtls_cipher_type_t cipher_alg; |
mbedtls_md_type_t md_alg; |
#endif |
p = key; |
end = p + keylen; |
if( pwdlen == 0 ) |
return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); |
/* |
* This function parses the EncryptedPrivateKeyInfo object (PKCS#8) |
* |
* EncryptedPrivateKeyInfo ::= SEQUENCE { |
* encryptionAlgorithm EncryptionAlgorithmIdentifier, |
* encryptedData EncryptedData |
* } |
* |
* EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier |
* |
* EncryptedData ::= OCTET STRING |
* |
* The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo |
* |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
} |
end = p + len; |
if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); |
buf = p; |
/* |
* Decrypt EncryptedData with appropriate PBE |
*/ |
#if defined(MBEDTLS_PKCS12_C) |
if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) |
{ |
if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, |
cipher_alg, md_alg, |
pwd, pwdlen, p, len, buf ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) |
return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); |
return( ret ); |
} |
decrypted = 1; |
} |
else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) |
{ |
if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, |
MBEDTLS_PKCS12_PBE_DECRYPT, |
pwd, pwdlen, |
p, len, buf ) ) != 0 ) |
{ |
return( ret ); |
} |
// Best guess for password mismatch when using RC4. If first tag is |
// not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE |
// |
if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) |
return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); |
decrypted = 1; |
} |
else |
#endif /* MBEDTLS_PKCS12_C */ |
#if defined(MBEDTLS_PKCS5_C) |
if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) |
{ |
if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, |
p, len, buf ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) |
return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); |
return( ret ); |
} |
decrypted = 1; |
} |
else |
#endif /* MBEDTLS_PKCS5_C */ |
{ |
((void) pwd); |
} |
if( decrypted == 0 ) |
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); |
return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); |
} |
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ |
/* |
* Parse a private key |
*/ |
int mbedtls_pk_parse_key( mbedtls_pk_context *pk, |
const unsigned char *key, size_t keylen, |
const unsigned char *pwd, size_t pwdlen ) |
{ |
int ret; |
const mbedtls_pk_info_t *pk_info; |
#if defined(MBEDTLS_PEM_PARSE_C) |
size_t len; |
mbedtls_pem_context pem; |
#endif |
PK_VALIDATE_RET( pk != NULL ); |
if( keylen == 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
PK_VALIDATE_RET( key != NULL ); |
#if defined(MBEDTLS_PEM_PARSE_C) |
mbedtls_pem_init( &pem ); |
#if defined(MBEDTLS_RSA_C) |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( key[keylen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN RSA PRIVATE KEY-----", |
"-----END RSA PRIVATE KEY-----", |
key, pwd, pwdlen, &len ); |
if( ret == 0 ) |
{ |
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); |
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || |
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), |
pem.buf, pem.buflen ) ) != 0 ) |
{ |
mbedtls_pk_free( pk ); |
} |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) |
return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); |
else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) |
return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
return( ret ); |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( key[keylen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN EC PRIVATE KEY-----", |
"-----END EC PRIVATE KEY-----", |
key, pwd, pwdlen, &len ); |
if( ret == 0 ) |
{ |
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); |
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || |
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), |
pem.buf, pem.buflen ) ) != 0 ) |
{ |
mbedtls_pk_free( pk ); |
} |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) |
return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); |
else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) |
return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
return( ret ); |
#endif /* MBEDTLS_ECP_C */ |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( key[keylen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN PRIVATE KEY-----", |
"-----END PRIVATE KEY-----", |
key, NULL, 0, &len ); |
if( ret == 0 ) |
{ |
if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, |
pem.buf, pem.buflen ) ) != 0 ) |
{ |
mbedtls_pk_free( pk ); |
} |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
return( ret ); |
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( key[keylen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN ENCRYPTED PRIVATE KEY-----", |
"-----END ENCRYPTED PRIVATE KEY-----", |
key, NULL, 0, &len ); |
if( ret == 0 ) |
{ |
if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, |
pem.buf, pem.buflen, |
pwd, pwdlen ) ) != 0 ) |
{ |
mbedtls_pk_free( pk ); |
} |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
return( ret ); |
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ |
#else |
((void) pwd); |
((void) pwdlen); |
#endif /* MBEDTLS_PEM_PARSE_C */ |
/* |
* At this point we only know it's not a PEM formatted key. Could be any |
* of the known DER encoded private key formats |
* |
* We try the different DER format parsers to see if one passes without |
* error |
*/ |
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) |
{ |
unsigned char *key_copy; |
if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) |
return( MBEDTLS_ERR_PK_ALLOC_FAILED ); |
memcpy( key_copy, key, keylen ); |
ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, |
pwd, pwdlen ); |
mbedtls_platform_zeroize( key_copy, keylen ); |
mbedtls_free( key_copy ); |
} |
if( ret == 0 ) |
return( 0 ); |
mbedtls_pk_free( pk ); |
mbedtls_pk_init( pk ); |
if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) |
{ |
return( ret ); |
} |
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ |
if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) |
return( 0 ); |
mbedtls_pk_free( pk ); |
mbedtls_pk_init( pk ); |
#if defined(MBEDTLS_RSA_C) |
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); |
if( mbedtls_pk_setup( pk, pk_info ) == 0 && |
pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) |
{ |
return( 0 ); |
} |
mbedtls_pk_free( pk ); |
mbedtls_pk_init( pk ); |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); |
if( mbedtls_pk_setup( pk, pk_info ) == 0 && |
pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), |
key, keylen ) == 0 ) |
{ |
return( 0 ); |
} |
mbedtls_pk_free( pk ); |
#endif /* MBEDTLS_ECP_C */ |
/* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, |
* it is ok to leave the PK context initialized but not |
* freed: It is the caller's responsibility to call pk_init() |
* before calling this function, and to call pk_free() |
* when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C |
* isn't, this leads to mbedtls_pk_free() being called |
* twice, once here and once by the caller, but this is |
* also ok and in line with the mbedtls_pk_free() calls |
* on failed PEM parsing attempts. */ |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
} |
/* |
* Parse a public key |
*/ |
int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, |
const unsigned char *key, size_t keylen ) |
{ |
int ret; |
unsigned char *p; |
#if defined(MBEDTLS_RSA_C) |
const mbedtls_pk_info_t *pk_info; |
#endif |
#if defined(MBEDTLS_PEM_PARSE_C) |
size_t len; |
mbedtls_pem_context pem; |
#endif |
PK_VALIDATE_RET( ctx != NULL ); |
if( keylen == 0 ) |
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
PK_VALIDATE_RET( key != NULL || keylen == 0 ); |
#if defined(MBEDTLS_PEM_PARSE_C) |
mbedtls_pem_init( &pem ); |
#if defined(MBEDTLS_RSA_C) |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( key[keylen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN RSA PUBLIC KEY-----", |
"-----END RSA PUBLIC KEY-----", |
key, NULL, 0, &len ); |
if( ret == 0 ) |
{ |
p = pem.buf; |
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) |
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) |
return( ret ); |
if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) |
mbedtls_pk_free( ctx ); |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
{ |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
#endif /* MBEDTLS_RSA_C */ |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( key[keylen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN PUBLIC KEY-----", |
"-----END PUBLIC KEY-----", |
key, NULL, 0, &len ); |
if( ret == 0 ) |
{ |
/* |
* Was PEM encoded |
*/ |
p = pem.buf; |
ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
{ |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
mbedtls_pem_free( &pem ); |
#endif /* MBEDTLS_PEM_PARSE_C */ |
#if defined(MBEDTLS_RSA_C) |
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) |
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) |
return( ret ); |
p = (unsigned char *)key; |
ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); |
if( ret == 0 ) |
{ |
return( ret ); |
} |
mbedtls_pk_free( ctx ); |
if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) |
{ |
return( ret ); |
} |
#endif /* MBEDTLS_RSA_C */ |
p = (unsigned char *) key; |
ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_PK_PARSE_C */ |
/programs/develop/libraries/kos_mbedtls/library/pkwrite.c |
---|
0,0 → 1,568 |
/* |
* Public Key layer for writing key files and structures |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PK_WRITE_C) |
#include "mbedtls/pk.h" |
#include "mbedtls/asn1write.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_RSA_C) |
#include "mbedtls/rsa.h" |
#endif |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/bignum.h" |
#include "mbedtls/ecp.h" |
#include "mbedtls/platform_util.h" |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
#include "mbedtls/ecdsa.h" |
#endif |
#if defined(MBEDTLS_PEM_WRITE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
/* Parameter validation macros based on platform_util.h */ |
#define PK_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) |
#define PK_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if defined(MBEDTLS_RSA_C) |
/* |
* RSAPublicKey ::= SEQUENCE { |
* modulus INTEGER, -- n |
* publicExponent INTEGER -- e |
* } |
*/ |
static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, |
mbedtls_rsa_context *rsa ) |
{ |
int ret; |
size_t len = 0; |
mbedtls_mpi T; |
mbedtls_mpi_init( &T ); |
/* Export E */ |
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export N */ |
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
end_of_export: |
mbedtls_mpi_free( &T ); |
if( ret < 0 ) |
return( ret ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return( (int) len ); |
} |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
/* |
* EC public key is an EC point |
*/ |
static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, |
mbedtls_ecp_keypair *ec ) |
{ |
int ret; |
size_t len = 0; |
unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; |
if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, |
MBEDTLS_ECP_PF_UNCOMPRESSED, |
&len, buf, sizeof( buf ) ) ) != 0 ) |
{ |
return( ret ); |
} |
if( *p < start || (size_t)( *p - start ) < len ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*p -= len; |
memcpy( *p, buf, len ); |
return( (int) len ); |
} |
/* |
* ECParameters ::= CHOICE { |
* namedCurve OBJECT IDENTIFIER |
* } |
*/ |
static int pk_write_ec_param( unsigned char **p, unsigned char *start, |
mbedtls_ecp_keypair *ec ) |
{ |
int ret; |
size_t len = 0; |
const char *oid; |
size_t oid_len; |
if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) |
return( ret ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); |
return( (int) len ); |
} |
/* |
* privateKey OCTET STRING -- always of length ceil(log2(n)/8) |
*/ |
static int pk_write_ec_private( unsigned char **p, unsigned char *start, |
mbedtls_ecp_keypair *ec ) |
{ |
int ret; |
size_t byte_length = ( ec->grp.pbits + 7 ) / 8; |
unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; |
ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length ); |
if( ret != 0 ) |
goto exit; |
ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); |
exit: |
mbedtls_platform_zeroize( tmp, byte_length ); |
return( ret ); |
} |
#endif /* MBEDTLS_ECP_C */ |
int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, |
const mbedtls_pk_context *key ) |
{ |
int ret; |
size_t len = 0; |
PK_VALIDATE_RET( p != NULL ); |
PK_VALIDATE_RET( *p != NULL ); |
PK_VALIDATE_RET( start != NULL ); |
PK_VALIDATE_RET( key != NULL ); |
#if defined(MBEDTLS_RSA_C) |
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) |
MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); |
else |
#endif |
#if defined(MBEDTLS_ECP_C) |
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) |
MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); |
else |
#endif |
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); |
return( (int) len ); |
} |
int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) |
{ |
int ret; |
unsigned char *c; |
size_t len = 0, par_len = 0, oid_len; |
const char *oid; |
PK_VALIDATE_RET( key != NULL ); |
if( size == 0 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
PK_VALIDATE_RET( buf != NULL ); |
c = buf + size; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); |
if( c - buf < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
/* |
* SubjectPublicKeyInfo ::= SEQUENCE { |
* algorithm AlgorithmIdentifier, |
* subjectPublicKey BIT STRING } |
*/ |
*--c = 0; |
len += 1; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); |
if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), |
&oid, &oid_len ) ) != 0 ) |
{ |
return( ret ); |
} |
#if defined(MBEDTLS_ECP_C) |
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) |
{ |
MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); |
} |
#endif |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, |
par_len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return( (int) len ); |
} |
int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) |
{ |
int ret; |
unsigned char *c; |
size_t len = 0; |
PK_VALIDATE_RET( key != NULL ); |
if( size == 0 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
PK_VALIDATE_RET( buf != NULL ); |
c = buf + size; |
#if defined(MBEDTLS_RSA_C) |
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) |
{ |
mbedtls_mpi T; /* Temporary holding the exported parameters */ |
mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); |
/* |
* Export the parameters one after another to avoid simultaneous copies. |
*/ |
mbedtls_mpi_init( &T ); |
/* Export QP */ |
if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export DQ */ |
if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export DP */ |
if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export Q */ |
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, |
&T, NULL, NULL ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export P */ |
if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, |
NULL, NULL, NULL ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export D */ |
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, |
NULL, &T, NULL ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export E */ |
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, |
NULL, NULL, &T ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
/* Export N */ |
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, |
NULL, NULL, NULL ) ) != 0 || |
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) |
goto end_of_export; |
len += ret; |
end_of_export: |
mbedtls_mpi_free( &T ); |
if( ret < 0 ) |
return( ret ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, |
buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
} |
else |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) |
{ |
mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); |
size_t pub_len = 0, par_len = 0; |
/* |
* RFC 5915, or SEC1 Appendix C.4 |
* |
* ECPrivateKey ::= SEQUENCE { |
* version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), |
* privateKey OCTET STRING, |
* parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, |
* publicKey [1] BIT STRING OPTIONAL |
* } |
*/ |
/* publicKey */ |
MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); |
if( c - buf < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--c = 0; |
pub_len += 1; |
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); |
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); |
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); |
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); |
len += pub_len; |
/* parameters */ |
MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); |
MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); |
MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); |
len += par_len; |
/* privateKey */ |
MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); |
/* version */ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
} |
else |
#endif /* MBEDTLS_ECP_C */ |
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); |
return( (int) len ); |
} |
#if defined(MBEDTLS_PEM_WRITE_C) |
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" |
#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" |
#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" |
#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" |
#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" |
#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" |
/* |
* Max sizes of key per types. Shown as tag + len (+ content). |
*/ |
#if defined(MBEDTLS_RSA_C) |
/* |
* RSA public keys: |
* SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 |
* algorithm AlgorithmIdentifier, 1 + 1 (sequence) |
* + 1 + 1 + 9 (rsa oid) |
* + 1 + 1 (params null) |
* subjectPublicKey BIT STRING } 1 + 3 + (1 + below) |
* RSAPublicKey ::= SEQUENCE { 1 + 3 |
* modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 |
* publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 |
* } |
*/ |
#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE |
/* |
* RSA private keys: |
* RSAPrivateKey ::= SEQUENCE { 1 + 3 |
* version Version, 1 + 1 + 1 |
* modulus INTEGER, 1 + 3 + MPI_MAX + 1 |
* publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 |
* privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 |
* prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
* prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
* exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
* exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
* coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 |
* otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) |
* } |
*/ |
#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ |
MBEDTLS_MPI_MAX_SIZE % 2 |
#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ |
+ 5 * MPI_MAX_SIZE_2 |
#else /* MBEDTLS_RSA_C */ |
#define RSA_PUB_DER_MAX_BYTES 0 |
#define RSA_PRV_DER_MAX_BYTES 0 |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_ECP_C) |
/* |
* EC public keys: |
* SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 |
* algorithm AlgorithmIdentifier, 1 + 1 (sequence) |
* + 1 + 1 + 7 (ec oid) |
* + 1 + 1 + 9 (namedCurve oid) |
* subjectPublicKey BIT STRING 1 + 2 + 1 [1] |
* + 1 (point format) [1] |
* + 2 * ECP_MAX (coords) [1] |
* } |
*/ |
#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES |
/* |
* EC private keys: |
* ECPrivateKey ::= SEQUENCE { 1 + 2 |
* version INTEGER , 1 + 1 + 1 |
* privateKey OCTET STRING, 1 + 1 + ECP_MAX |
* parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) |
* publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above |
* } |
*/ |
#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES |
#else /* MBEDTLS_ECP_C */ |
#define ECP_PUB_DER_MAX_BYTES 0 |
#define ECP_PRV_DER_MAX_BYTES 0 |
#endif /* MBEDTLS_ECP_C */ |
#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ |
RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES |
#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ |
RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES |
int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) |
{ |
int ret; |
unsigned char output_buf[PUB_DER_MAX_BYTES]; |
size_t olen = 0; |
PK_VALIDATE_RET( key != NULL ); |
PK_VALIDATE_RET( buf != NULL || size == 0 ); |
if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, |
sizeof(output_buf) ) ) < 0 ) |
{ |
return( ret ); |
} |
if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, |
output_buf + sizeof(output_buf) - ret, |
ret, buf, size, &olen ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) |
{ |
int ret; |
unsigned char output_buf[PRV_DER_MAX_BYTES]; |
const char *begin, *end; |
size_t olen = 0; |
PK_VALIDATE_RET( key != NULL ); |
PK_VALIDATE_RET( buf != NULL || size == 0 ); |
if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) |
return( ret ); |
#if defined(MBEDTLS_RSA_C) |
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) |
{ |
begin = PEM_BEGIN_PRIVATE_KEY_RSA; |
end = PEM_END_PRIVATE_KEY_RSA; |
} |
else |
#endif |
#if defined(MBEDTLS_ECP_C) |
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) |
{ |
begin = PEM_BEGIN_PRIVATE_KEY_EC; |
end = PEM_END_PRIVATE_KEY_EC; |
} |
else |
#endif |
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); |
if( ( ret = mbedtls_pem_write_buffer( begin, end, |
output_buf + sizeof(output_buf) - ret, |
ret, buf, size, &olen ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_PEM_WRITE_C */ |
#endif /* MBEDTLS_PK_WRITE_C */ |
/programs/develop/libraries/kos_mbedtls/library/platform.c |
---|
0,0 → 1,350 |
/* |
* Platform abstraction layer |
* |
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#include "mbedtls/platform_util.h" |
/* The compile time configuration of memory allocation via the macros |
* MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime |
* configuration via mbedtls_platform_set_calloc_free(). So, omit everything |
* related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ |
#if defined(MBEDTLS_PLATFORM_MEMORY) && \ |
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ |
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) |
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) |
static void *platform_calloc_uninit( size_t n, size_t size ) |
{ |
((void) n); |
((void) size); |
return( NULL ); |
} |
#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ |
#if !defined(MBEDTLS_PLATFORM_STD_FREE) |
static void platform_free_uninit( void *ptr ) |
{ |
((void) ptr); |
} |
#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_FREE */ |
static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; |
static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; |
void * mbedtls_calloc( size_t nmemb, size_t size ) |
{ |
return (*mbedtls_calloc_func)( nmemb, size ); |
} |
void mbedtls_free( void * ptr ) |
{ |
(*mbedtls_free_func)( ptr ); |
} |
int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), |
void (*free_func)( void * ) ) |
{ |
mbedtls_calloc_func = calloc_func; |
mbedtls_free_func = free_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PLATFORM_MEMORY && |
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && |
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ |
#if defined(_WIN32) |
#include <stdarg.h> |
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) |
{ |
int ret; |
va_list argp; |
/* Avoid calling the invalid parameter handler by checking ourselves */ |
if( s == NULL || n == 0 || fmt == NULL ) |
return( -1 ); |
va_start( argp, fmt ); |
#if defined(_TRUNCATE) && !defined(__MINGW32__) |
ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); |
#else |
ret = _vsnprintf( s, n, fmt, argp ); |
if( ret < 0 || (size_t) ret == n ) |
{ |
s[n-1] = '\0'; |
ret = -1; |
} |
#endif |
va_end( argp ); |
return( ret ); |
} |
#endif |
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) |
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) |
/* |
* Make dummy function to prevent NULL pointer dereferences |
*/ |
static int platform_snprintf_uninit( char * s, size_t n, |
const char * format, ... ) |
{ |
((void) s); |
((void) n); |
((void) format); |
return( 0 ); |
} |
#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ |
int (*mbedtls_snprintf)( char * s, size_t n, |
const char * format, |
... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; |
int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, |
const char * format, |
... ) ) |
{ |
mbedtls_snprintf = snprintf_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ |
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) |
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) |
/* |
* Make dummy function to prevent NULL pointer dereferences |
*/ |
static int platform_printf_uninit( const char *format, ... ) |
{ |
((void) format); |
return( 0 ); |
} |
#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ |
int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; |
int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) |
{ |
mbedtls_printf = printf_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ |
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) |
#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) |
/* |
* Make dummy function to prevent NULL pointer dereferences |
*/ |
static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) |
{ |
((void) stream); |
((void) format); |
return( 0 ); |
} |
#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ |
int (*mbedtls_fprintf)( FILE *, const char *, ... ) = |
MBEDTLS_PLATFORM_STD_FPRINTF; |
int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) |
{ |
mbedtls_fprintf = fprintf_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ |
#if defined(MBEDTLS_PLATFORM_EXIT_ALT) |
#if !defined(MBEDTLS_PLATFORM_STD_EXIT) |
/* |
* Make dummy function to prevent NULL pointer dereferences |
*/ |
static void platform_exit_uninit( int status ) |
{ |
((void) status); |
} |
#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ |
void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; |
int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) |
{ |
mbedtls_exit = exit_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ |
#if defined(MBEDTLS_HAVE_TIME) |
#if defined(MBEDTLS_PLATFORM_TIME_ALT) |
#if !defined(MBEDTLS_PLATFORM_STD_TIME) |
/* |
* Make dummy function to prevent NULL pointer dereferences |
*/ |
static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) |
{ |
((void) timer); |
return( 0 ); |
} |
#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_TIME */ |
mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; |
int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) |
{ |
mbedtls_time = time_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PLATFORM_TIME_ALT */ |
#endif /* MBEDTLS_HAVE_TIME */ |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) |
/* Default implementations for the platform independent seed functions use |
* standard libc file functions to read from and write to a pre-defined filename |
*/ |
int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) |
{ |
FILE *file; |
size_t n; |
if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) |
return( -1 ); |
if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) |
{ |
fclose( file ); |
mbedtls_platform_zeroize( buf, buf_len ); |
return( -1 ); |
} |
fclose( file ); |
return( (int)n ); |
} |
int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) |
{ |
FILE *file; |
size_t n; |
if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) |
return -1; |
if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) |
{ |
fclose( file ); |
return -1; |
} |
fclose( file ); |
return( (int)n ); |
} |
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ |
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) |
#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) |
/* |
* Make dummy function to prevent NULL pointer dereferences |
*/ |
static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) |
{ |
((void) buf); |
((void) buf_len); |
return( -1 ); |
} |
#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ |
#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) |
/* |
* Make dummy function to prevent NULL pointer dereferences |
*/ |
static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) |
{ |
((void) buf); |
((void) buf_len); |
return( -1 ); |
} |
#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit |
#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ |
int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = |
MBEDTLS_PLATFORM_STD_NV_SEED_READ; |
int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = |
MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; |
int mbedtls_platform_set_nv_seed( |
int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), |
int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) |
{ |
mbedtls_nv_seed_read = nv_seed_read_func; |
mbedtls_nv_seed_write = nv_seed_write_func; |
return( 0 ); |
} |
#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ |
#endif /* MBEDTLS_ENTROPY_NV_SEED */ |
#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) |
/* |
* Placeholder platform setup that does nothing by default |
*/ |
int mbedtls_platform_setup( mbedtls_platform_context *ctx ) |
{ |
(void)ctx; |
return( 0 ); |
} |
/* |
* Placeholder platform teardown that does nothing by default |
*/ |
void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) |
{ |
(void)ctx; |
} |
#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ |
#endif /* MBEDTLS_PLATFORM_C */ |
/programs/develop/libraries/kos_mbedtls/library/platform_util.c |
---|
0,0 → 1,141 |
/* |
* Common and shared functions used by multiple modules in the Mbed TLS |
* library. |
* |
* Copyright (C) 2018, Arm Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of Mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* Ensure gmtime_r is available even with -std=c99; must be defined before |
* config.h, which pulls in glibc's features.h. Harmless on other platforms. |
*/ |
#if !defined(_POSIX_C_SOURCE) |
#define _POSIX_C_SOURCE 200112L |
#endif |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#include "mbedtls/platform_util.h" |
#include "mbedtls/platform.h" |
#include "mbedtls/threading.h" |
#include <stddef.h> |
#include <string.h> |
#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) |
/* |
* This implementation should never be optimized out by the compiler |
* |
* This implementation for mbedtls_platform_zeroize() was inspired from Colin |
* Percival's blog article at: |
* |
* http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html |
* |
* It uses a volatile function pointer to the standard memset(). Because the |
* pointer is volatile the compiler expects it to change at |
* any time and will not optimize out the call that could potentially perform |
* other operations on the input buffer instead of just setting it to 0. |
* Nevertheless, as pointed out by davidtgoldblatt on Hacker News |
* (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for |
* details), optimizations of the following form are still possible: |
* |
* if( memset_func != memset ) |
* memset_func( buf, 0, len ); |
* |
* Note that it is extremely difficult to guarantee that |
* mbedtls_platform_zeroize() will not be optimized out by aggressive compilers |
* in a portable way. For this reason, Mbed TLS also provides the configuration |
* option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure |
* mbedtls_platform_zeroize() to use a suitable implementation for their |
* platform and needs. |
*/ |
static void * (* const volatile memset_func)( void *, int, size_t ) = memset; |
void mbedtls_platform_zeroize( void *buf, size_t len ) |
{ |
MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL ); |
if( len > 0 ) |
memset_func( buf, 0, len ); |
} |
#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ |
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) |
#include <time.h> |
#if !defined(_WIN32) && (defined(unix) || \ |
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ |
defined(__MACH__))) |
#include <unistd.h> |
#endif /* !_WIN32 && (unix || __unix || __unix__ || |
* (__APPLE__ && __MACH__)) */ |
#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ |
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ |
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) |
/* |
* This is a convenience shorthand macro to avoid checking the long |
* preprocessor conditions above. Ideally, we could expose this macro in |
* platform_util.h and simply use it in platform_util.c, threading.c and |
* threading.h. However, this macro is not part of the Mbed TLS public API, so |
* we keep it private by only defining it in this file |
*/ |
#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) |
#define PLATFORM_UTIL_USE_GMTIME |
#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ |
#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ |
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ |
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ |
struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, |
struct tm *tm_buf ) |
{ |
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) |
return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); |
#elif !defined(PLATFORM_UTIL_USE_GMTIME) |
return( gmtime_r( tt, tm_buf ) ); |
#else |
struct tm *lt; |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) |
return( NULL ); |
#endif /* MBEDTLS_THREADING_C */ |
lt = gmtime( tt ); |
if( lt != NULL ) |
{ |
memcpy( tm_buf, lt, sizeof( struct tm ) ); |
} |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) |
return( NULL ); |
#endif /* MBEDTLS_THREADING_C */ |
return( ( lt == NULL ) ? NULL : tm_buf ); |
#endif /* _WIN32 && !EFIX64 && !EFI32 */ |
} |
#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ |
/programs/develop/libraries/kos_mbedtls/library/poly1305.c |
---|
0,0 → 1,561 |
/** |
* \file poly1305.c |
* |
* \brief Poly1305 authentication algorithm. |
* |
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_POLY1305_C) |
#include "mbedtls/poly1305.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_POLY1305_ALT) |
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ |
!defined(inline) && !defined(__cplusplus) |
#define inline __inline |
#endif |
/* Parameter validation macros */ |
#define POLY1305_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) |
#define POLY1305_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) |
#define BYTES_TO_U32_LE( data, offset ) \ |
( (uint32_t) (data)[offset] \ |
| (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \ |
| (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \ |
| (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \ |
) |
/* |
* Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. |
* However we provided an alternative for platforms without such a multiplier. |
*/ |
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) |
static uint64_t mul64( uint32_t a, uint32_t b ) |
{ |
/* a = al + 2**16 ah, b = bl + 2**16 bh */ |
const uint16_t al = (uint16_t) a; |
const uint16_t bl = (uint16_t) b; |
const uint16_t ah = a >> 16; |
const uint16_t bh = b >> 16; |
/* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ |
const uint32_t lo = (uint32_t) al * bl; |
const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; |
const uint32_t hi = (uint32_t) ah * bh; |
return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); |
} |
#else |
static inline uint64_t mul64( uint32_t a, uint32_t b ) |
{ |
return( (uint64_t) a * b ); |
} |
#endif |
/** |
* \brief Process blocks with Poly1305. |
* |
* \param ctx The Poly1305 context. |
* \param nblocks Number of blocks to process. Note that this |
* function only processes full blocks. |
* \param input Buffer containing the input block(s). |
* \param needs_padding Set to 0 if the padding bit has already been |
* applied to the input data before calling this |
* function. Otherwise, set this parameter to 1. |
*/ |
static void poly1305_process( mbedtls_poly1305_context *ctx, |
size_t nblocks, |
const unsigned char *input, |
uint32_t needs_padding ) |
{ |
uint64_t d0, d1, d2, d3; |
uint32_t acc0, acc1, acc2, acc3, acc4; |
uint32_t r0, r1, r2, r3; |
uint32_t rs1, rs2, rs3; |
size_t offset = 0U; |
size_t i; |
r0 = ctx->r[0]; |
r1 = ctx->r[1]; |
r2 = ctx->r[2]; |
r3 = ctx->r[3]; |
rs1 = r1 + ( r1 >> 2U ); |
rs2 = r2 + ( r2 >> 2U ); |
rs3 = r3 + ( r3 >> 2U ); |
acc0 = ctx->acc[0]; |
acc1 = ctx->acc[1]; |
acc2 = ctx->acc[2]; |
acc3 = ctx->acc[3]; |
acc4 = ctx->acc[4]; |
/* Process full blocks */ |
for( i = 0U; i < nblocks; i++ ) |
{ |
/* The input block is treated as a 128-bit little-endian integer */ |
d0 = BYTES_TO_U32_LE( input, offset + 0 ); |
d1 = BYTES_TO_U32_LE( input, offset + 4 ); |
d2 = BYTES_TO_U32_LE( input, offset + 8 ); |
d3 = BYTES_TO_U32_LE( input, offset + 12 ); |
/* Compute: acc += (padded) block as a 130-bit integer */ |
d0 += (uint64_t) acc0; |
d1 += (uint64_t) acc1 + ( d0 >> 32U ); |
d2 += (uint64_t) acc2 + ( d1 >> 32U ); |
d3 += (uint64_t) acc3 + ( d2 >> 32U ); |
acc0 = (uint32_t) d0; |
acc1 = (uint32_t) d1; |
acc2 = (uint32_t) d2; |
acc3 = (uint32_t) d3; |
acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; |
/* Compute: acc *= r */ |
d0 = mul64( acc0, r0 ) + |
mul64( acc1, rs3 ) + |
mul64( acc2, rs2 ) + |
mul64( acc3, rs1 ); |
d1 = mul64( acc0, r1 ) + |
mul64( acc1, r0 ) + |
mul64( acc2, rs3 ) + |
mul64( acc3, rs2 ) + |
mul64( acc4, rs1 ); |
d2 = mul64( acc0, r2 ) + |
mul64( acc1, r1 ) + |
mul64( acc2, r0 ) + |
mul64( acc3, rs3 ) + |
mul64( acc4, rs2 ); |
d3 = mul64( acc0, r3 ) + |
mul64( acc1, r2 ) + |
mul64( acc2, r1 ) + |
mul64( acc3, r0 ) + |
mul64( acc4, rs3 ); |
acc4 *= r0; |
/* Compute: acc %= (2^130 - 5) (partial remainder) */ |
d1 += ( d0 >> 32 ); |
d2 += ( d1 >> 32 ); |
d3 += ( d2 >> 32 ); |
acc0 = (uint32_t) d0; |
acc1 = (uint32_t) d1; |
acc2 = (uint32_t) d2; |
acc3 = (uint32_t) d3; |
acc4 = (uint32_t) ( d3 >> 32 ) + acc4; |
d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); |
acc4 &= 3U; |
acc0 = (uint32_t) d0; |
d0 = (uint64_t) acc1 + ( d0 >> 32U ); |
acc1 = (uint32_t) d0; |
d0 = (uint64_t) acc2 + ( d0 >> 32U ); |
acc2 = (uint32_t) d0; |
d0 = (uint64_t) acc3 + ( d0 >> 32U ); |
acc3 = (uint32_t) d0; |
d0 = (uint64_t) acc4 + ( d0 >> 32U ); |
acc4 = (uint32_t) d0; |
offset += POLY1305_BLOCK_SIZE_BYTES; |
} |
ctx->acc[0] = acc0; |
ctx->acc[1] = acc1; |
ctx->acc[2] = acc2; |
ctx->acc[3] = acc3; |
ctx->acc[4] = acc4; |
} |
/** |
* \brief Compute the Poly1305 MAC |
* |
* \param ctx The Poly1305 context. |
* \param mac The buffer to where the MAC is written. Must be |
* big enough to contain the 16-byte MAC. |
*/ |
static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, |
unsigned char mac[16] ) |
{ |
uint64_t d; |
uint32_t g0, g1, g2, g3, g4; |
uint32_t acc0, acc1, acc2, acc3, acc4; |
uint32_t mask; |
uint32_t mask_inv; |
acc0 = ctx->acc[0]; |
acc1 = ctx->acc[1]; |
acc2 = ctx->acc[2]; |
acc3 = ctx->acc[3]; |
acc4 = ctx->acc[4]; |
/* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. |
* We do this by calculating acc - (2^130 - 5), then checking if |
* the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) |
*/ |
/* Calculate acc + -(2^130 - 5) */ |
d = ( (uint64_t) acc0 + 5U ); |
g0 = (uint32_t) d; |
d = ( (uint64_t) acc1 + ( d >> 32 ) ); |
g1 = (uint32_t) d; |
d = ( (uint64_t) acc2 + ( d >> 32 ) ); |
g2 = (uint32_t) d; |
d = ( (uint64_t) acc3 + ( d >> 32 ) ); |
g3 = (uint32_t) d; |
g4 = acc4 + (uint32_t) ( d >> 32U ); |
/* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ |
mask = (uint32_t) 0U - ( g4 >> 2U ); |
mask_inv = ~mask; |
/* If 131st bit is set then acc=g, otherwise, acc is unmodified */ |
acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); |
acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); |
acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); |
acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); |
/* Add 's' */ |
d = (uint64_t) acc0 + ctx->s[0]; |
acc0 = (uint32_t) d; |
d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); |
acc1 = (uint32_t) d; |
d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); |
acc2 = (uint32_t) d; |
acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); |
/* Compute MAC (128 least significant bits of the accumulator) */ |
mac[ 0] = (unsigned char)( acc0 ); |
mac[ 1] = (unsigned char)( acc0 >> 8 ); |
mac[ 2] = (unsigned char)( acc0 >> 16 ); |
mac[ 3] = (unsigned char)( acc0 >> 24 ); |
mac[ 4] = (unsigned char)( acc1 ); |
mac[ 5] = (unsigned char)( acc1 >> 8 ); |
mac[ 6] = (unsigned char)( acc1 >> 16 ); |
mac[ 7] = (unsigned char)( acc1 >> 24 ); |
mac[ 8] = (unsigned char)( acc2 ); |
mac[ 9] = (unsigned char)( acc2 >> 8 ); |
mac[10] = (unsigned char)( acc2 >> 16 ); |
mac[11] = (unsigned char)( acc2 >> 24 ); |
mac[12] = (unsigned char)( acc3 ); |
mac[13] = (unsigned char)( acc3 >> 8 ); |
mac[14] = (unsigned char)( acc3 >> 16 ); |
mac[15] = (unsigned char)( acc3 >> 24 ); |
} |
void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) |
{ |
POLY1305_VALIDATE( ctx != NULL ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); |
} |
void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); |
} |
int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, |
const unsigned char key[32] ) |
{ |
POLY1305_VALIDATE_RET( ctx != NULL ); |
POLY1305_VALIDATE_RET( key != NULL ); |
/* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ |
ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU; |
ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU; |
ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU; |
ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU; |
ctx->s[0] = BYTES_TO_U32_LE( key, 16 ); |
ctx->s[1] = BYTES_TO_U32_LE( key, 20 ); |
ctx->s[2] = BYTES_TO_U32_LE( key, 24 ); |
ctx->s[3] = BYTES_TO_U32_LE( key, 28 ); |
/* Initial accumulator state */ |
ctx->acc[0] = 0U; |
ctx->acc[1] = 0U; |
ctx->acc[2] = 0U; |
ctx->acc[3] = 0U; |
ctx->acc[4] = 0U; |
/* Queue initially empty */ |
mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); |
ctx->queue_len = 0U; |
return( 0 ); |
} |
int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
size_t offset = 0U; |
size_t remaining = ilen; |
size_t queue_free_len; |
size_t nblocks; |
POLY1305_VALIDATE_RET( ctx != NULL ); |
POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); |
if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) |
{ |
queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); |
if( ilen < queue_free_len ) |
{ |
/* Not enough data to complete the block. |
* Store this data with the other leftovers. |
*/ |
memcpy( &ctx->queue[ctx->queue_len], |
input, |
ilen ); |
ctx->queue_len += ilen; |
remaining = 0U; |
} |
else |
{ |
/* Enough data to produce a complete block */ |
memcpy( &ctx->queue[ctx->queue_len], |
input, |
queue_free_len ); |
ctx->queue_len = 0U; |
poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ |
offset += queue_free_len; |
remaining -= queue_free_len; |
} |
} |
if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) |
{ |
nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; |
poly1305_process( ctx, nblocks, &input[offset], 1U ); |
offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; |
remaining %= POLY1305_BLOCK_SIZE_BYTES; |
} |
if( remaining > 0U ) |
{ |
/* Store partial block */ |
ctx->queue_len = remaining; |
memcpy( ctx->queue, &input[offset], remaining ); |
} |
return( 0 ); |
} |
int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, |
unsigned char mac[16] ) |
{ |
POLY1305_VALIDATE_RET( ctx != NULL ); |
POLY1305_VALIDATE_RET( mac != NULL ); |
/* Process any leftover data */ |
if( ctx->queue_len > 0U ) |
{ |
/* Add padding bit */ |
ctx->queue[ctx->queue_len] = 1U; |
ctx->queue_len++; |
/* Pad with zeroes */ |
memset( &ctx->queue[ctx->queue_len], |
0, |
POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); |
poly1305_process( ctx, 1U, /* Process 1 block */ |
ctx->queue, 0U ); /* Already padded above */ |
} |
poly1305_compute_mac( ctx, mac ); |
return( 0 ); |
} |
int mbedtls_poly1305_mac( const unsigned char key[32], |
const unsigned char *input, |
size_t ilen, |
unsigned char mac[16] ) |
{ |
mbedtls_poly1305_context ctx; |
int ret; |
POLY1305_VALIDATE_RET( key != NULL ); |
POLY1305_VALIDATE_RET( mac != NULL ); |
POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); |
mbedtls_poly1305_init( &ctx ); |
ret = mbedtls_poly1305_starts( &ctx, key ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_poly1305_update( &ctx, input, ilen ); |
if( ret != 0 ) |
goto cleanup; |
ret = mbedtls_poly1305_finish( &ctx, mac ); |
cleanup: |
mbedtls_poly1305_free( &ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_POLY1305_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
static const unsigned char test_keys[2][32] = |
{ |
{ |
0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, |
0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, |
0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, |
0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b |
}, |
{ |
0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, |
0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, |
0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, |
0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 |
} |
}; |
static const unsigned char test_data[2][127] = |
{ |
{ |
0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, |
0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, |
0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, |
0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, |
0x75, 0x70 |
}, |
{ |
0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, |
0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, |
0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, |
0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, |
0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, |
0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, |
0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, |
0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, |
0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, |
0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, |
0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, |
0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, |
0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, |
0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, |
0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, |
0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e |
} |
}; |
static const size_t test_data_len[2] = |
{ |
34U, |
127U |
}; |
static const unsigned char test_mac[2][16] = |
{ |
{ |
0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, |
0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 |
}, |
{ |
0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, |
0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 |
} |
}; |
#define ASSERT( cond, args ) \ |
do \ |
{ \ |
if( ! ( cond ) ) \ |
{ \ |
if( verbose != 0 ) \ |
mbedtls_printf args; \ |
\ |
return( -1 ); \ |
} \ |
} \ |
while( 0 ) |
int mbedtls_poly1305_self_test( int verbose ) |
{ |
unsigned char mac[16]; |
unsigned i; |
int ret; |
for( i = 0U; i < 2U; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " Poly1305 test %u ", i ); |
ret = mbedtls_poly1305_mac( test_keys[i], |
test_data[i], |
test_data_len[i], |
mac ); |
ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); |
ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_POLY1305_C */ |
/programs/develop/libraries/kos_mbedtls/library/ripemd160.c |
---|
0,0 → 1,561 |
/* |
* RIPE MD-160 implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The RIPEMD-160 algorithm was designed by RIPE in 1996 |
* http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html |
* http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_RIPEMD160_C) |
#include "mbedtls/ripemd160.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_RIPEMD160_ALT) |
/* |
* 32-bit integer manipulation macros (little endian) |
*/ |
#ifndef GET_UINT32_LE |
#define GET_UINT32_LE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] ) \ |
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 3] << 24 ); \ |
} |
#endif |
#ifndef PUT_UINT32_LE |
#define PUT_UINT32_LE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ |
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ |
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ |
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ |
} |
#endif |
void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); |
} |
void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); |
} |
void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, |
const mbedtls_ripemd160_context *src ) |
{ |
*dst = *src; |
} |
/* |
* RIPEMD-160 context setup |
*/ |
int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) |
{ |
ctx->total[0] = 0; |
ctx->total[1] = 0; |
ctx->state[0] = 0x67452301; |
ctx->state[1] = 0xEFCDAB89; |
ctx->state[2] = 0x98BADCFE; |
ctx->state[3] = 0x10325476; |
ctx->state[4] = 0xC3D2E1F0; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) |
{ |
mbedtls_ripemd160_starts_ret( ctx ); |
} |
#endif |
#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) |
/* |
* Process one block |
*/ |
int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, |
const unsigned char data[64] ) |
{ |
uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; |
GET_UINT32_LE( X[ 0], data, 0 ); |
GET_UINT32_LE( X[ 1], data, 4 ); |
GET_UINT32_LE( X[ 2], data, 8 ); |
GET_UINT32_LE( X[ 3], data, 12 ); |
GET_UINT32_LE( X[ 4], data, 16 ); |
GET_UINT32_LE( X[ 5], data, 20 ); |
GET_UINT32_LE( X[ 6], data, 24 ); |
GET_UINT32_LE( X[ 7], data, 28 ); |
GET_UINT32_LE( X[ 8], data, 32 ); |
GET_UINT32_LE( X[ 9], data, 36 ); |
GET_UINT32_LE( X[10], data, 40 ); |
GET_UINT32_LE( X[11], data, 44 ); |
GET_UINT32_LE( X[12], data, 48 ); |
GET_UINT32_LE( X[13], data, 52 ); |
GET_UINT32_LE( X[14], data, 56 ); |
GET_UINT32_LE( X[15], data, 60 ); |
A = Ap = ctx->state[0]; |
B = Bp = ctx->state[1]; |
C = Cp = ctx->state[2]; |
D = Dp = ctx->state[3]; |
E = Ep = ctx->state[4]; |
#define F1( x, y, z ) ( (x) ^ (y) ^ (z) ) |
#define F2( x, y, z ) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) |
#define F3( x, y, z ) ( ( (x) | ~(y) ) ^ (z) ) |
#define F4( x, y, z ) ( ( (x) & (z) ) | ( (y) & ~(z) ) ) |
#define F5( x, y, z ) ( (x) ^ ( (y) | ~(z) ) ) |
#define S( x, n ) ( ( (x) << (n) ) | ( (x) >> (32 - (n)) ) ) |
#define P( a, b, c, d, e, r, s, f, k ) \ |
do \ |
{ \ |
(a) += f( (b), (c), (d) ) + X[r] + (k); \ |
(a) = S( (a), (s) ) + (e); \ |
(c) = S( (c), 10 ); \ |
} while( 0 ) |
#define P2( a, b, c, d, e, r, s, rp, sp ) \ |
do \ |
{ \ |
P( (a), (b), (c), (d), (e), (r), (s), F, K ); \ |
P( a ## p, b ## p, c ## p, d ## p, e ## p, \ |
(rp), (sp), Fp, Kp ); \ |
} while( 0 ) |
#define F F1 |
#define K 0x00000000 |
#define Fp F5 |
#define Kp 0x50A28BE6 |
P2( A, B, C, D, E, 0, 11, 5, 8 ); |
P2( E, A, B, C, D, 1, 14, 14, 9 ); |
P2( D, E, A, B, C, 2, 15, 7, 9 ); |
P2( C, D, E, A, B, 3, 12, 0, 11 ); |
P2( B, C, D, E, A, 4, 5, 9, 13 ); |
P2( A, B, C, D, E, 5, 8, 2, 15 ); |
P2( E, A, B, C, D, 6, 7, 11, 15 ); |
P2( D, E, A, B, C, 7, 9, 4, 5 ); |
P2( C, D, E, A, B, 8, 11, 13, 7 ); |
P2( B, C, D, E, A, 9, 13, 6, 7 ); |
P2( A, B, C, D, E, 10, 14, 15, 8 ); |
P2( E, A, B, C, D, 11, 15, 8, 11 ); |
P2( D, E, A, B, C, 12, 6, 1, 14 ); |
P2( C, D, E, A, B, 13, 7, 10, 14 ); |
P2( B, C, D, E, A, 14, 9, 3, 12 ); |
P2( A, B, C, D, E, 15, 8, 12, 6 ); |
#undef F |
#undef K |
#undef Fp |
#undef Kp |
#define F F2 |
#define K 0x5A827999 |
#define Fp F4 |
#define Kp 0x5C4DD124 |
P2( E, A, B, C, D, 7, 7, 6, 9 ); |
P2( D, E, A, B, C, 4, 6, 11, 13 ); |
P2( C, D, E, A, B, 13, 8, 3, 15 ); |
P2( B, C, D, E, A, 1, 13, 7, 7 ); |
P2( A, B, C, D, E, 10, 11, 0, 12 ); |
P2( E, A, B, C, D, 6, 9, 13, 8 ); |
P2( D, E, A, B, C, 15, 7, 5, 9 ); |
P2( C, D, E, A, B, 3, 15, 10, 11 ); |
P2( B, C, D, E, A, 12, 7, 14, 7 ); |
P2( A, B, C, D, E, 0, 12, 15, 7 ); |
P2( E, A, B, C, D, 9, 15, 8, 12 ); |
P2( D, E, A, B, C, 5, 9, 12, 7 ); |
P2( C, D, E, A, B, 2, 11, 4, 6 ); |
P2( B, C, D, E, A, 14, 7, 9, 15 ); |
P2( A, B, C, D, E, 11, 13, 1, 13 ); |
P2( E, A, B, C, D, 8, 12, 2, 11 ); |
#undef F |
#undef K |
#undef Fp |
#undef Kp |
#define F F3 |
#define K 0x6ED9EBA1 |
#define Fp F3 |
#define Kp 0x6D703EF3 |
P2( D, E, A, B, C, 3, 11, 15, 9 ); |
P2( C, D, E, A, B, 10, 13, 5, 7 ); |
P2( B, C, D, E, A, 14, 6, 1, 15 ); |
P2( A, B, C, D, E, 4, 7, 3, 11 ); |
P2( E, A, B, C, D, 9, 14, 7, 8 ); |
P2( D, E, A, B, C, 15, 9, 14, 6 ); |
P2( C, D, E, A, B, 8, 13, 6, 6 ); |
P2( B, C, D, E, A, 1, 15, 9, 14 ); |
P2( A, B, C, D, E, 2, 14, 11, 12 ); |
P2( E, A, B, C, D, 7, 8, 8, 13 ); |
P2( D, E, A, B, C, 0, 13, 12, 5 ); |
P2( C, D, E, A, B, 6, 6, 2, 14 ); |
P2( B, C, D, E, A, 13, 5, 10, 13 ); |
P2( A, B, C, D, E, 11, 12, 0, 13 ); |
P2( E, A, B, C, D, 5, 7, 4, 7 ); |
P2( D, E, A, B, C, 12, 5, 13, 5 ); |
#undef F |
#undef K |
#undef Fp |
#undef Kp |
#define F F4 |
#define K 0x8F1BBCDC |
#define Fp F2 |
#define Kp 0x7A6D76E9 |
P2( C, D, E, A, B, 1, 11, 8, 15 ); |
P2( B, C, D, E, A, 9, 12, 6, 5 ); |
P2( A, B, C, D, E, 11, 14, 4, 8 ); |
P2( E, A, B, C, D, 10, 15, 1, 11 ); |
P2( D, E, A, B, C, 0, 14, 3, 14 ); |
P2( C, D, E, A, B, 8, 15, 11, 14 ); |
P2( B, C, D, E, A, 12, 9, 15, 6 ); |
P2( A, B, C, D, E, 4, 8, 0, 14 ); |
P2( E, A, B, C, D, 13, 9, 5, 6 ); |
P2( D, E, A, B, C, 3, 14, 12, 9 ); |
P2( C, D, E, A, B, 7, 5, 2, 12 ); |
P2( B, C, D, E, A, 15, 6, 13, 9 ); |
P2( A, B, C, D, E, 14, 8, 9, 12 ); |
P2( E, A, B, C, D, 5, 6, 7, 5 ); |
P2( D, E, A, B, C, 6, 5, 10, 15 ); |
P2( C, D, E, A, B, 2, 12, 14, 8 ); |
#undef F |
#undef K |
#undef Fp |
#undef Kp |
#define F F5 |
#define K 0xA953FD4E |
#define Fp F1 |
#define Kp 0x00000000 |
P2( B, C, D, E, A, 4, 9, 12, 8 ); |
P2( A, B, C, D, E, 0, 15, 15, 5 ); |
P2( E, A, B, C, D, 5, 5, 10, 12 ); |
P2( D, E, A, B, C, 9, 11, 4, 9 ); |
P2( C, D, E, A, B, 7, 6, 1, 12 ); |
P2( B, C, D, E, A, 12, 8, 5, 5 ); |
P2( A, B, C, D, E, 2, 13, 8, 14 ); |
P2( E, A, B, C, D, 10, 12, 7, 6 ); |
P2( D, E, A, B, C, 14, 5, 6, 8 ); |
P2( C, D, E, A, B, 1, 12, 2, 13 ); |
P2( B, C, D, E, A, 3, 13, 13, 6 ); |
P2( A, B, C, D, E, 8, 14, 14, 5 ); |
P2( E, A, B, C, D, 11, 11, 0, 15 ); |
P2( D, E, A, B, C, 6, 8, 3, 13 ); |
P2( C, D, E, A, B, 15, 5, 9, 11 ); |
P2( B, C, D, E, A, 13, 6, 11, 11 ); |
#undef F |
#undef K |
#undef Fp |
#undef Kp |
C = ctx->state[1] + C + Dp; |
ctx->state[1] = ctx->state[2] + D + Ep; |
ctx->state[2] = ctx->state[3] + E + Ap; |
ctx->state[3] = ctx->state[4] + A + Bp; |
ctx->state[4] = ctx->state[0] + B + Cp; |
ctx->state[0] = C; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, |
const unsigned char data[64] ) |
{ |
mbedtls_internal_ripemd160_process( ctx, data ); |
} |
#endif |
#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ |
/* |
* RIPEMD-160 process buffer |
*/ |
int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
int ret; |
size_t fill; |
uint32_t left; |
if( ilen == 0 ) |
return( 0 ); |
left = ctx->total[0] & 0x3F; |
fill = 64 - left; |
ctx->total[0] += (uint32_t) ilen; |
ctx->total[0] &= 0xFFFFFFFF; |
if( ctx->total[0] < (uint32_t) ilen ) |
ctx->total[1]++; |
if( left && ilen >= fill ) |
{ |
memcpy( (void *) (ctx->buffer + left), input, fill ); |
if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
input += fill; |
ilen -= fill; |
left = 0; |
} |
while( ilen >= 64 ) |
{ |
if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) |
return( ret ); |
input += 64; |
ilen -= 64; |
} |
if( ilen > 0 ) |
{ |
memcpy( (void *) (ctx->buffer + left), input, ilen ); |
} |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
mbedtls_ripemd160_update_ret( ctx, input, ilen ); |
} |
#endif |
static const unsigned char ripemd160_padding[64] = |
{ |
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
}; |
/* |
* RIPEMD-160 final digest |
*/ |
int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, |
unsigned char output[20] ) |
{ |
int ret; |
uint32_t last, padn; |
uint32_t high, low; |
unsigned char msglen[8]; |
high = ( ctx->total[0] >> 29 ) |
| ( ctx->total[1] << 3 ); |
low = ( ctx->total[0] << 3 ); |
PUT_UINT32_LE( low, msglen, 0 ); |
PUT_UINT32_LE( high, msglen, 4 ); |
last = ctx->total[0] & 0x3F; |
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); |
ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); |
if( ret != 0 ) |
return( ret ); |
ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); |
if( ret != 0 ) |
return( ret ); |
PUT_UINT32_LE( ctx->state[0], output, 0 ); |
PUT_UINT32_LE( ctx->state[1], output, 4 ); |
PUT_UINT32_LE( ctx->state[2], output, 8 ); |
PUT_UINT32_LE( ctx->state[3], output, 12 ); |
PUT_UINT32_LE( ctx->state[4], output, 16 ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, |
unsigned char output[20] ) |
{ |
mbedtls_ripemd160_finish_ret( ctx, output ); |
} |
#endif |
#endif /* ! MBEDTLS_RIPEMD160_ALT */ |
/* |
* output = RIPEMD-160( input buffer ) |
*/ |
int mbedtls_ripemd160_ret( const unsigned char *input, |
size_t ilen, |
unsigned char output[20] ) |
{ |
int ret; |
mbedtls_ripemd160_context ctx; |
mbedtls_ripemd160_init( &ctx ); |
if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_ripemd160_free( &ctx ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_ripemd160( const unsigned char *input, |
size_t ilen, |
unsigned char output[20] ) |
{ |
mbedtls_ripemd160_ret( input, ilen, output ); |
} |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* Test vectors from the RIPEMD-160 paper and |
* http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC |
*/ |
#define TESTS 8 |
static const unsigned char ripemd160_test_str[TESTS][81] = |
{ |
{ "" }, |
{ "a" }, |
{ "abc" }, |
{ "message digest" }, |
{ "abcdefghijklmnopqrstuvwxyz" }, |
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, |
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, |
{ "12345678901234567890123456789012345678901234567890123456789012" |
"345678901234567890" }, |
}; |
static const size_t ripemd160_test_strlen[TESTS] = |
{ |
0, 1, 3, 14, 26, 56, 62, 80 |
}; |
static const unsigned char ripemd160_test_md[TESTS][20] = |
{ |
{ 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, |
0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, |
{ 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, |
0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, |
{ 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, |
0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, |
{ 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, |
0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, |
{ 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, |
0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, |
{ 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, |
0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, |
{ 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, |
0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, |
{ 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, |
0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_ripemd160_self_test( int verbose ) |
{ |
int i, ret = 0; |
unsigned char output[20]; |
memset( output, 0, sizeof output ); |
for( i = 0; i < TESTS; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); |
ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], |
ripemd160_test_strlen[i], output ); |
if( ret != 0 ) |
goto fail; |
if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) |
{ |
ret = 1; |
goto fail; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
fail: |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_RIPEMD160_C */ |
/programs/develop/libraries/kos_mbedtls/library/rsa.c |
---|
0,0 → 1,2731 |
/* |
* The RSA public-key cryptosystem |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The following sources were referenced in the design of this implementation |
* of the RSA algorithm: |
* |
* [1] A method for obtaining digital signatures and public-key cryptosystems |
* R Rivest, A Shamir, and L Adleman |
* http://people.csail.mit.edu/rivest/pubs.html#RSA78 |
* |
* [2] Handbook of Applied Cryptography - 1997, Chapter 8 |
* Menezes, van Oorschot and Vanstone |
* |
* [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks |
* Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and |
* Stefan Mangard |
* https://arxiv.org/abs/1702.08719v2 |
* |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_RSA_C) |
#include "mbedtls/rsa.h" |
#include "mbedtls/rsa_internal.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PKCS1_V21) |
#include "mbedtls/md.h" |
#endif |
#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) |
#include <stdlib.h> |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#if !defined(MBEDTLS_RSA_ALT) |
/* Parameter validation macros */ |
#define RSA_VALIDATE_RET( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) |
#define RSA_VALIDATE( cond ) \ |
MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if defined(MBEDTLS_PKCS1_V15) |
/* constant-time buffer comparison */ |
static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) |
{ |
size_t i; |
const unsigned char *A = (const unsigned char *) a; |
const unsigned char *B = (const unsigned char *) b; |
unsigned char diff = 0; |
for( i = 0; i < n; i++ ) |
diff |= A[i] ^ B[i]; |
return( diff ); |
} |
#endif /* MBEDTLS_PKCS1_V15 */ |
int mbedtls_rsa_import( mbedtls_rsa_context *ctx, |
const mbedtls_mpi *N, |
const mbedtls_mpi *P, const mbedtls_mpi *Q, |
const mbedtls_mpi *D, const mbedtls_mpi *E ) |
{ |
int ret; |
RSA_VALIDATE_RET( ctx != NULL ); |
if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || |
( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || |
( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || |
( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || |
( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
} |
if( N != NULL ) |
ctx->len = mbedtls_mpi_size( &ctx->N ); |
return( 0 ); |
} |
int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, |
unsigned char const *N, size_t N_len, |
unsigned char const *P, size_t P_len, |
unsigned char const *Q, size_t Q_len, |
unsigned char const *D, size_t D_len, |
unsigned char const *E, size_t E_len ) |
{ |
int ret = 0; |
RSA_VALIDATE_RET( ctx != NULL ); |
if( N != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); |
ctx->len = mbedtls_mpi_size( &ctx->N ); |
} |
if( P != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); |
if( Q != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); |
if( D != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); |
if( E != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); |
cleanup: |
if( ret != 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
return( 0 ); |
} |
/* |
* Checks whether the context fields are set in such a way |
* that the RSA primitives will be able to execute without error. |
* It does *not* make guarantees for consistency of the parameters. |
*/ |
static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, |
int blinding_needed ) |
{ |
#if !defined(MBEDTLS_RSA_NO_CRT) |
/* blinding_needed is only used for NO_CRT to decide whether |
* P,Q need to be present or not. */ |
((void) blinding_needed); |
#endif |
if( ctx->len != mbedtls_mpi_size( &ctx->N ) || |
ctx->len > MBEDTLS_MPI_MAX_SIZE ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
/* |
* 1. Modular exponentiation needs positive, odd moduli. |
*/ |
/* Modular exponentiation wrt. N is always used for |
* RSA public key operations. */ |
if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || |
mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
#if !defined(MBEDTLS_RSA_NO_CRT) |
/* Modular exponentiation for P and Q is only |
* used for private key operations and if CRT |
* is used. */ |
if( is_priv && |
( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || |
mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || |
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || |
mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
#endif /* !MBEDTLS_RSA_NO_CRT */ |
/* |
* 2. Exponents must be positive |
*/ |
/* Always need E for public key operations */ |
if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_RSA_NO_CRT) |
/* For private key operations, use D or DP & DQ |
* as (unblinded) exponents. */ |
if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
#else |
if( is_priv && |
( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || |
mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
#endif /* MBEDTLS_RSA_NO_CRT */ |
/* Blinding shouldn't make exponents negative either, |
* so check that P, Q >= 1 if that hasn't yet been |
* done as part of 1. */ |
#if defined(MBEDTLS_RSA_NO_CRT) |
if( is_priv && blinding_needed && |
( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || |
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
#endif |
/* It wouldn't lead to an error if it wasn't satisfied, |
* but check for QP >= 1 nonetheless. */ |
#if !defined(MBEDTLS_RSA_NO_CRT) |
if( is_priv && |
mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
#endif |
return( 0 ); |
} |
int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) |
{ |
int ret = 0; |
int have_N, have_P, have_Q, have_D, have_E; |
#if !defined(MBEDTLS_RSA_NO_CRT) |
int have_DP, have_DQ, have_QP; |
#endif |
int n_missing, pq_missing, d_missing, is_pub, is_priv; |
RSA_VALIDATE_RET( ctx != NULL ); |
have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); |
have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); |
have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); |
have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); |
have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); |
#if !defined(MBEDTLS_RSA_NO_CRT) |
have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); |
have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); |
have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); |
#endif |
/* |
* Check whether provided parameters are enough |
* to deduce all others. The following incomplete |
* parameter sets for private keys are supported: |
* |
* (1) P, Q missing. |
* (2) D and potentially N missing. |
* |
*/ |
n_missing = have_P && have_Q && have_D && have_E; |
pq_missing = have_N && !have_P && !have_Q && have_D && have_E; |
d_missing = have_P && have_Q && !have_D && have_E; |
is_pub = have_N && !have_P && !have_Q && !have_D && have_E; |
/* These three alternatives are mutually exclusive */ |
is_priv = n_missing || pq_missing || d_missing; |
if( !is_priv && !is_pub ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* |
* Step 1: Deduce N if P, Q are provided. |
*/ |
if( !have_N && have_P && have_Q ) |
{ |
if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, |
&ctx->Q ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
} |
ctx->len = mbedtls_mpi_size( &ctx->N ); |
} |
/* |
* Step 2: Deduce and verify all remaining core parameters. |
*/ |
if( pq_missing ) |
{ |
ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, |
&ctx->P, &ctx->Q ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
} |
else if( d_missing ) |
{ |
if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, |
&ctx->Q, |
&ctx->E, |
&ctx->D ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
} |
} |
/* |
* Step 3: Deduce all additional parameters specific |
* to our current RSA implementation. |
*/ |
#if !defined(MBEDTLS_RSA_NO_CRT) |
if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) |
{ |
ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, |
&ctx->DP, &ctx->DQ, &ctx->QP ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
} |
#endif /* MBEDTLS_RSA_NO_CRT */ |
/* |
* Step 3: Basic sanity checks |
*/ |
return( rsa_check_context( ctx, is_priv, 1 ) ); |
} |
int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, |
unsigned char *N, size_t N_len, |
unsigned char *P, size_t P_len, |
unsigned char *Q, size_t Q_len, |
unsigned char *D, size_t D_len, |
unsigned char *E, size_t E_len ) |
{ |
int ret = 0; |
int is_priv; |
RSA_VALIDATE_RET( ctx != NULL ); |
/* Check if key is private or public */ |
is_priv = |
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; |
if( !is_priv ) |
{ |
/* If we're trying to export private parameters for a public key, |
* something must be wrong. */ |
if( P != NULL || Q != NULL || D != NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
if( N != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); |
if( P != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); |
if( Q != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); |
if( D != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); |
if( E != NULL ) |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); |
cleanup: |
return( ret ); |
} |
int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, |
mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, |
mbedtls_mpi *D, mbedtls_mpi *E ) |
{ |
int ret; |
int is_priv; |
RSA_VALIDATE_RET( ctx != NULL ); |
/* Check if key is private or public */ |
is_priv = |
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; |
if( !is_priv ) |
{ |
/* If we're trying to export private parameters for a public key, |
* something must be wrong. */ |
if( P != NULL || Q != NULL || D != NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
/* Export all requested core parameters. */ |
if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || |
( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || |
( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || |
( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || |
( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
/* |
* Export CRT parameters |
* This must also be implemented if CRT is not used, for being able to |
* write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt |
* can be used in this case. |
*/ |
int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, |
mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) |
{ |
int ret; |
int is_priv; |
RSA_VALIDATE_RET( ctx != NULL ); |
/* Check if key is private or public */ |
is_priv = |
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && |
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; |
if( !is_priv ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
#if !defined(MBEDTLS_RSA_NO_CRT) |
/* Export all requested blinding parameters. */ |
if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || |
( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || |
( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
} |
#else |
if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, |
DP, DQ, QP ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); |
} |
#endif |
return( 0 ); |
} |
/* |
* Initialize an RSA context |
*/ |
void mbedtls_rsa_init( mbedtls_rsa_context *ctx, |
int padding, |
int hash_id ) |
{ |
RSA_VALIDATE( ctx != NULL ); |
RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || |
padding == MBEDTLS_RSA_PKCS_V21 ); |
memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); |
mbedtls_rsa_set_padding( ctx, padding, hash_id ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &ctx->mutex ); |
#endif |
} |
/* |
* Set padding for an existing RSA context |
*/ |
void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, |
int hash_id ) |
{ |
RSA_VALIDATE( ctx != NULL ); |
RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || |
padding == MBEDTLS_RSA_PKCS_V21 ); |
ctx->padding = padding; |
ctx->hash_id = hash_id; |
} |
/* |
* Get length in bytes of RSA modulus |
*/ |
size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) |
{ |
return( ctx->len ); |
} |
#if defined(MBEDTLS_GENPRIME) |
/* |
* Generate an RSA keypair |
* |
* This generation method follows the RSA key pair generation procedure of |
* FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. |
*/ |
int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
unsigned int nbits, int exponent ) |
{ |
int ret; |
mbedtls_mpi H, G, L; |
int prime_quality = 0; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( f_rng != NULL ); |
if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* |
* If the modulus is 1024 bit long or shorter, then the security strength of |
* the RSA algorithm is less than or equal to 80 bits and therefore an error |
* rate of 2^-80 is sufficient. |
*/ |
if( nbits > 1024 ) |
prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; |
mbedtls_mpi_init( &H ); |
mbedtls_mpi_init( &G ); |
mbedtls_mpi_init( &L ); |
/* |
* find primes P and Q with Q < P so that: |
* 1. |P-Q| > 2^( nbits / 2 - 100 ) |
* 2. GCD( E, (P-1)*(Q-1) ) == 1 |
* 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); |
do |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, |
prime_quality, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, |
prime_quality, f_rng, p_rng ) ); |
/* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); |
if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) |
continue; |
/* not required by any standards, but some users rely on the fact that P > Q */ |
if( H.s < 0 ) |
mbedtls_mpi_swap( &ctx->P, &ctx->Q ); |
/* Temporarily replace P,Q by P-1, Q-1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); |
/* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); |
if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) |
continue; |
/* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); |
if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) |
continue; |
break; |
} |
while( 1 ); |
/* Restore P,Q */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); |
ctx->len = mbedtls_mpi_size( &ctx->N ); |
#if !defined(MBEDTLS_RSA_NO_CRT) |
/* |
* DP = D mod (P - 1) |
* DQ = D mod (Q - 1) |
* QP = Q^-1 mod P |
*/ |
MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, |
&ctx->DP, &ctx->DQ, &ctx->QP ) ); |
#endif /* MBEDTLS_RSA_NO_CRT */ |
/* Double-check */ |
MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); |
cleanup: |
mbedtls_mpi_free( &H ); |
mbedtls_mpi_free( &G ); |
mbedtls_mpi_free( &L ); |
if( ret != 0 ) |
{ |
mbedtls_rsa_free( ctx ); |
return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_GENPRIME */ |
/* |
* Check a public RSA key |
*/ |
int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) |
{ |
RSA_VALIDATE_RET( ctx != NULL ); |
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || |
mbedtls_mpi_bitlen( &ctx->E ) < 2 || |
mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
return( 0 ); |
} |
/* |
* Check for the consistency of all fields in an RSA private key context |
*/ |
int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) |
{ |
RSA_VALIDATE_RET( ctx != NULL ); |
if( mbedtls_rsa_check_pubkey( ctx ) != 0 || |
rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, |
&ctx->D, &ctx->E, NULL, NULL ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
#if !defined(MBEDTLS_RSA_NO_CRT) |
else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, |
&ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
#endif |
return( 0 ); |
} |
/* |
* Check if contexts holding a public and private key match |
*/ |
int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, |
const mbedtls_rsa_context *prv ) |
{ |
RSA_VALIDATE_RET( pub != NULL ); |
RSA_VALIDATE_RET( prv != NULL ); |
if( mbedtls_rsa_check_pubkey( pub ) != 0 || |
mbedtls_rsa_check_privkey( prv ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || |
mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); |
} |
return( 0 ); |
} |
/* |
* Do an RSA public key operation |
*/ |
int mbedtls_rsa_public( mbedtls_rsa_context *ctx, |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
size_t olen; |
mbedtls_mpi T; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
RSA_VALIDATE_RET( output != NULL ); |
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
mbedtls_mpi_init( &T ); |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); |
if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) |
{ |
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; |
goto cleanup; |
} |
olen = ctx->len; |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); |
cleanup: |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
mbedtls_mpi_free( &T ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); |
return( 0 ); |
} |
/* |
* Generate or update blinding values, see section 10 of: |
* KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, |
* DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer |
* Berlin Heidelberg, 1996. p. 104-113. |
*/ |
static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) |
{ |
int ret, count = 0; |
if( ctx->Vf.p != NULL ) |
{ |
/* We already have blinding values, just update them by squaring */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); |
goto cleanup; |
} |
/* Unblinding value: Vf = random number, invertible mod N */ |
do { |
if( count++ > 10 ) |
return( MBEDTLS_ERR_RSA_RNG_FAILED ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); |
} while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); |
/* Blinding value: Vi = Vf^(-e) mod N */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); |
cleanup: |
return( ret ); |
} |
/* |
* Exponent blinding supposed to prevent side-channel attacks using multiple |
* traces of measurements to recover the RSA key. The more collisions are there, |
* the more bits of the key can be recovered. See [3]. |
* |
* Collecting n collisions with m bit long blinding value requires 2^(m-m/n) |
* observations on avarage. |
* |
* For example with 28 byte blinding to achieve 2 collisions the adversary has |
* to make 2^112 observations on avarage. |
* |
* (With the currently (as of 2017 April) known best algorithms breaking 2048 |
* bit RSA requires approximately as much time as trying out 2^112 random keys. |
* Thus in this sense with 28 byte blinding the security is not reduced by |
* side-channel attacks like the one in [3]) |
* |
* This countermeasure does not help if the key recovery is possible with a |
* single trace. |
*/ |
#define RSA_EXPONENT_BLINDING 28 |
/* |
* Do an RSA private key operation |
*/ |
int mbedtls_rsa_private( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
const unsigned char *input, |
unsigned char *output ) |
{ |
int ret; |
size_t olen; |
/* Temporary holding the result */ |
mbedtls_mpi T; |
/* Temporaries holding P-1, Q-1 and the |
* exponent blinding factor, respectively. */ |
mbedtls_mpi P1, Q1, R; |
#if !defined(MBEDTLS_RSA_NO_CRT) |
/* Temporaries holding the results mod p resp. mod q. */ |
mbedtls_mpi TP, TQ; |
/* Temporaries holding the blinded exponents for |
* the mod p resp. mod q computation (if used). */ |
mbedtls_mpi DP_blind, DQ_blind; |
/* Pointers to actual exponents to be used - either the unblinded |
* or the blinded ones, depending on the presence of a PRNG. */ |
mbedtls_mpi *DP = &ctx->DP; |
mbedtls_mpi *DQ = &ctx->DQ; |
#else |
/* Temporary holding the blinded exponent (if used). */ |
mbedtls_mpi D_blind; |
/* Pointer to actual exponent to be used - either the unblinded |
* or the blinded one, depending on the presence of a PRNG. */ |
mbedtls_mpi *D = &ctx->D; |
#endif /* MBEDTLS_RSA_NO_CRT */ |
/* Temporaries holding the initial input and the double |
* checked result; should be the same in the end. */ |
mbedtls_mpi I, C; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
RSA_VALIDATE_RET( output != NULL ); |
if( rsa_check_context( ctx, 1 /* private key checks */, |
f_rng != NULL /* blinding y/n */ ) != 0 ) |
{ |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
/* MPI Initialization */ |
mbedtls_mpi_init( &T ); |
mbedtls_mpi_init( &P1 ); |
mbedtls_mpi_init( &Q1 ); |
mbedtls_mpi_init( &R ); |
if( f_rng != NULL ) |
{ |
#if defined(MBEDTLS_RSA_NO_CRT) |
mbedtls_mpi_init( &D_blind ); |
#else |
mbedtls_mpi_init( &DP_blind ); |
mbedtls_mpi_init( &DQ_blind ); |
#endif |
} |
#if !defined(MBEDTLS_RSA_NO_CRT) |
mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); |
#endif |
mbedtls_mpi_init( &I ); |
mbedtls_mpi_init( &C ); |
/* End of MPI initialization */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); |
if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) |
{ |
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); |
if( f_rng != NULL ) |
{ |
/* |
* Blinding |
* T = T * Vi mod N |
*/ |
MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); |
/* |
* Exponent blinding |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); |
#if defined(MBEDTLS_RSA_NO_CRT) |
/* |
* D_blind = ( P - 1 ) * ( Q - 1 ) * R + D |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, |
f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); |
D = &D_blind; |
#else |
/* |
* DP_blind = ( P - 1 ) * R + DP |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, |
f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, |
&ctx->DP ) ); |
DP = &DP_blind; |
/* |
* DQ_blind = ( Q - 1 ) * R + DQ |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, |
f_rng, p_rng ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, |
&ctx->DQ ) ); |
DQ = &DQ_blind; |
#endif /* MBEDTLS_RSA_NO_CRT */ |
} |
#if defined(MBEDTLS_RSA_NO_CRT) |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); |
#else |
/* |
* Faster decryption using the CRT |
* |
* TP = input ^ dP mod P |
* TQ = input ^ dQ mod Q |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); |
/* |
* T = (TP - TQ) * (Q^-1 mod P) mod P |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); |
/* |
* T = TQ + T * Q |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); |
#endif /* MBEDTLS_RSA_NO_CRT */ |
if( f_rng != NULL ) |
{ |
/* |
* Unblind |
* T = T * Vf mod N |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); |
} |
/* Verify the result to prevent glitching attacks. */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, |
&ctx->N, &ctx->RN ) ); |
if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; |
goto cleanup; |
} |
olen = ctx->len; |
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); |
cleanup: |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
mbedtls_mpi_free( &P1 ); |
mbedtls_mpi_free( &Q1 ); |
mbedtls_mpi_free( &R ); |
if( f_rng != NULL ) |
{ |
#if defined(MBEDTLS_RSA_NO_CRT) |
mbedtls_mpi_free( &D_blind ); |
#else |
mbedtls_mpi_free( &DP_blind ); |
mbedtls_mpi_free( &DQ_blind ); |
#endif |
} |
mbedtls_mpi_free( &T ); |
#if !defined(MBEDTLS_RSA_NO_CRT) |
mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); |
#endif |
mbedtls_mpi_free( &C ); |
mbedtls_mpi_free( &I ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); |
return( 0 ); |
} |
#if defined(MBEDTLS_PKCS1_V21) |
/** |
* Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. |
* |
* \param dst buffer to mask |
* \param dlen length of destination buffer |
* \param src source of the mask generation |
* \param slen length of the source buffer |
* \param md_ctx message digest context to use |
*/ |
static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, |
size_t slen, mbedtls_md_context_t *md_ctx ) |
{ |
unsigned char mask[MBEDTLS_MD_MAX_SIZE]; |
unsigned char counter[4]; |
unsigned char *p; |
unsigned int hlen; |
size_t i, use_len; |
int ret = 0; |
memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); |
memset( counter, 0, 4 ); |
hlen = mbedtls_md_get_size( md_ctx->md_info ); |
/* Generate and apply dbMask */ |
p = dst; |
while( dlen > 0 ) |
{ |
use_len = hlen; |
if( dlen < hlen ) |
use_len = dlen; |
if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) |
goto exit; |
for( i = 0; i < use_len; ++i ) |
*p++ ^= mask[i]; |
counter[3]++; |
dlen -= use_len; |
} |
exit: |
mbedtls_platform_zeroize( mask, sizeof( mask ) ); |
return( ret ); |
} |
#endif /* MBEDTLS_PKCS1_V21 */ |
#if defined(MBEDTLS_PKCS1_V21) |
/* |
* Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function |
*/ |
int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
const unsigned char *label, size_t label_len, |
size_t ilen, |
const unsigned char *input, |
unsigned char *output ) |
{ |
size_t olen; |
int ret; |
unsigned char *p = output; |
unsigned int hlen; |
const mbedtls_md_info_t *md_info; |
mbedtls_md_context_t md_ctx; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( output != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
RSA_VALIDATE_RET( label_len == 0 || label != NULL ); |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( f_rng == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
olen = ctx->len; |
hlen = mbedtls_md_get_size( md_info ); |
/* first comparison checks for overflow */ |
if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
memset( output, 0, olen ); |
*p++ = 0; |
/* Generate a random octet string seed */ |
if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) |
return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); |
p += hlen; |
/* Construct DB */ |
if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) |
return( ret ); |
p += hlen; |
p += olen - 2 * hlen - 2 - ilen; |
*p++ = 1; |
memcpy( p, input, ilen ); |
mbedtls_md_init( &md_ctx ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) |
goto exit; |
/* maskedDB: Apply dbMask to DB */ |
if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, |
&md_ctx ) ) != 0 ) |
goto exit; |
/* maskedSeed: Apply seedMask to seed */ |
if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, |
&md_ctx ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_md_free( &md_ctx ); |
if( ret != 0 ) |
return( ret ); |
return( ( mode == MBEDTLS_RSA_PUBLIC ) |
? mbedtls_rsa_public( ctx, output, output ) |
: mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); |
} |
#endif /* MBEDTLS_PKCS1_V21 */ |
#if defined(MBEDTLS_PKCS1_V15) |
/* |
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function |
*/ |
int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, size_t ilen, |
const unsigned char *input, |
unsigned char *output ) |
{ |
size_t nb_pad, olen; |
int ret; |
unsigned char *p = output; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( output != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
olen = ctx->len; |
/* first comparison checks for overflow */ |
if( ilen + 11 < ilen || olen < ilen + 11 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
nb_pad = olen - 3 - ilen; |
*p++ = 0; |
if( mode == MBEDTLS_RSA_PUBLIC ) |
{ |
if( f_rng == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
*p++ = MBEDTLS_RSA_CRYPT; |
while( nb_pad-- > 0 ) |
{ |
int rng_dl = 100; |
do { |
ret = f_rng( p_rng, p, 1 ); |
} while( *p == 0 && --rng_dl && ret == 0 ); |
/* Check if RNG failed to generate data */ |
if( rng_dl == 0 || ret != 0 ) |
return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); |
p++; |
} |
} |
else |
{ |
*p++ = MBEDTLS_RSA_SIGN; |
while( nb_pad-- > 0 ) |
*p++ = 0xFF; |
} |
*p++ = 0; |
memcpy( p, input, ilen ); |
return( ( mode == MBEDTLS_RSA_PUBLIC ) |
? mbedtls_rsa_public( ctx, output, output ) |
: mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); |
} |
#endif /* MBEDTLS_PKCS1_V15 */ |
/* |
* Add the message padding, then do an RSA operation |
*/ |
int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, size_t ilen, |
const unsigned char *input, |
unsigned char *output ) |
{ |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( output != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
switch( ctx->padding ) |
{ |
#if defined(MBEDTLS_PKCS1_V15) |
case MBEDTLS_RSA_PKCS_V15: |
return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, |
input, output ); |
#endif |
#if defined(MBEDTLS_PKCS1_V21) |
case MBEDTLS_RSA_PKCS_V21: |
return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, |
ilen, input, output ); |
#endif |
default: |
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); |
} |
} |
#if defined(MBEDTLS_PKCS1_V21) |
/* |
* Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function |
*/ |
int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
const unsigned char *label, size_t label_len, |
size_t *olen, |
const unsigned char *input, |
unsigned char *output, |
size_t output_max_len ) |
{ |
int ret; |
size_t ilen, i, pad_len; |
unsigned char *p, bad, pad_done; |
unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; |
unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; |
unsigned int hlen; |
const mbedtls_md_info_t *md_info; |
mbedtls_md_context_t md_ctx; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); |
RSA_VALIDATE_RET( label_len == 0 || label != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
RSA_VALIDATE_RET( olen != NULL ); |
/* |
* Parameters sanity checks |
*/ |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
ilen = ctx->len; |
if( ilen < 16 || ilen > sizeof( buf ) ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hlen = mbedtls_md_get_size( md_info ); |
// checking for integer underflow |
if( 2 * hlen + 2 > ilen ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* |
* RSA operation |
*/ |
ret = ( mode == MBEDTLS_RSA_PUBLIC ) |
? mbedtls_rsa_public( ctx, input, buf ) |
: mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); |
if( ret != 0 ) |
goto cleanup; |
/* |
* Unmask data and generate lHash |
*/ |
mbedtls_md_init( &md_ctx ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) |
{ |
mbedtls_md_free( &md_ctx ); |
goto cleanup; |
} |
/* seed: Apply seedMask to maskedSeed */ |
if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, |
&md_ctx ) ) != 0 || |
/* DB: Apply dbMask to maskedDB */ |
( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, |
&md_ctx ) ) != 0 ) |
{ |
mbedtls_md_free( &md_ctx ); |
goto cleanup; |
} |
mbedtls_md_free( &md_ctx ); |
/* Generate lHash */ |
if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) |
goto cleanup; |
/* |
* Check contents, in "constant-time" |
*/ |
p = buf; |
bad = 0; |
bad |= *p++; /* First byte must be 0 */ |
p += hlen; /* Skip seed */ |
/* Check lHash */ |
for( i = 0; i < hlen; i++ ) |
bad |= lhash[i] ^ *p++; |
/* Get zero-padding len, but always read till end of buffer |
* (minus one, for the 01 byte) */ |
pad_len = 0; |
pad_done = 0; |
for( i = 0; i < ilen - 2 * hlen - 2; i++ ) |
{ |
pad_done |= p[i]; |
pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; |
} |
p += pad_len; |
bad |= *p++ ^ 0x01; |
/* |
* The only information "leaked" is whether the padding was correct or not |
* (eg, no data is copied if it was not correct). This meets the |
* recommendations in PKCS#1 v2.2: an opponent cannot distinguish between |
* the different error conditions. |
*/ |
if( bad != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_INVALID_PADDING; |
goto cleanup; |
} |
if( ilen - ( p - buf ) > output_max_len ) |
{ |
ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; |
goto cleanup; |
} |
*olen = ilen - (p - buf); |
memcpy( output, p, *olen ); |
ret = 0; |
cleanup: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); |
return( ret ); |
} |
#endif /* MBEDTLS_PKCS1_V21 */ |
#if defined(MBEDTLS_PKCS1_V15) |
/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches. |
* |
* \param value The value to analyze. |
* \return Zero if \p value is zero, otherwise all-bits-one. |
*/ |
static unsigned all_or_nothing_int( unsigned value ) |
{ |
/* MSVC has a warning about unary minus on unsigned, but this is |
* well-defined and precisely what we want to do here */ |
#if defined(_MSC_VER) |
#pragma warning( push ) |
#pragma warning( disable : 4146 ) |
#endif |
return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); |
#if defined(_MSC_VER) |
#pragma warning( pop ) |
#endif |
} |
/** Check whether a size is out of bounds, without branches. |
* |
* This is equivalent to `size > max`, but is likely to be compiled to |
* to code using bitwise operation rather than a branch. |
* |
* \param size Size to check. |
* \param max Maximum desired value for \p size. |
* \return \c 0 if `size <= max`. |
* \return \c 1 if `size > max`. |
*/ |
static unsigned size_greater_than( size_t size, size_t max ) |
{ |
/* Return the sign bit (1 for negative) of (max - size). */ |
return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) ); |
} |
/** Choose between two integer values, without branches. |
* |
* This is equivalent to `cond ? if1 : if0`, but is likely to be compiled |
* to code using bitwise operation rather than a branch. |
* |
* \param cond Condition to test. |
* \param if1 Value to use if \p cond is nonzero. |
* \param if0 Value to use if \p cond is zero. |
* \return \c if1 if \p cond is nonzero, otherwise \c if0. |
*/ |
static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 ) |
{ |
unsigned mask = all_or_nothing_int( cond ); |
return( ( mask & if1 ) | (~mask & if0 ) ); |
} |
/** Shift some data towards the left inside a buffer without leaking |
* the length of the data through side channels. |
* |
* `mem_move_to_left(start, total, offset)` is functionally equivalent to |
* ``` |
* memmove(start, start + offset, total - offset); |
* memset(start + offset, 0, total - offset); |
* ``` |
* but it strives to use a memory access pattern (and thus total timing) |
* that does not depend on \p offset. This timing independence comes at |
* the expense of performance. |
* |
* \param start Pointer to the start of the buffer. |
* \param total Total size of the buffer. |
* \param offset Offset from which to copy \p total - \p offset bytes. |
*/ |
static void mem_move_to_left( void *start, |
size_t total, |
size_t offset ) |
{ |
volatile unsigned char *buf = start; |
size_t i, n; |
if( total == 0 ) |
return; |
for( i = 0; i < total; i++ ) |
{ |
unsigned no_op = size_greater_than( total - offset, i ); |
/* The first `total - offset` passes are a no-op. The last |
* `offset` passes shift the data one byte to the left and |
* zero out the last byte. */ |
for( n = 0; n < total - 1; n++ ) |
{ |
unsigned char current = buf[n]; |
unsigned char next = buf[n+1]; |
buf[n] = if_int( no_op, current, next ); |
} |
buf[total-1] = if_int( no_op, buf[total-1], 0 ); |
} |
} |
/* |
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function |
*/ |
int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, size_t *olen, |
const unsigned char *input, |
unsigned char *output, |
size_t output_max_len ) |
{ |
int ret; |
size_t ilen, i, plaintext_max_size; |
unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; |
/* The following variables take sensitive values: their value must |
* not leak into the observable behavior of the function other than |
* the designated outputs (output, olen, return value). Otherwise |
* this would open the execution of the function to |
* side-channel-based variants of the Bleichenbacher padding oracle |
* attack. Potential side channels include overall timing, memory |
* access patterns (especially visible to an adversary who has access |
* to a shared memory cache), and branches (especially visible to |
* an adversary who has access to a shared code cache or to a shared |
* branch predictor). */ |
size_t pad_count = 0; |
unsigned bad = 0; |
unsigned char pad_done = 0; |
size_t plaintext_size = 0; |
unsigned output_too_large; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
RSA_VALIDATE_RET( olen != NULL ); |
ilen = ctx->len; |
plaintext_max_size = ( output_max_len > ilen - 11 ? |
ilen - 11 : |
output_max_len ); |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( ilen < 16 || ilen > sizeof( buf ) ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
ret = ( mode == MBEDTLS_RSA_PUBLIC ) |
? mbedtls_rsa_public( ctx, input, buf ) |
: mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); |
if( ret != 0 ) |
goto cleanup; |
/* Check and get padding length in constant time and constant |
* memory trace. The first byte must be 0. */ |
bad |= buf[0]; |
if( mode == MBEDTLS_RSA_PRIVATE ) |
{ |
/* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 |
* where PS must be at least 8 nonzero bytes. */ |
bad |= buf[1] ^ MBEDTLS_RSA_CRYPT; |
/* Read the whole buffer. Set pad_done to nonzero if we find |
* the 0x00 byte and remember the padding length in pad_count. */ |
for( i = 2; i < ilen; i++ ) |
{ |
pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1; |
pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; |
} |
} |
else |
{ |
/* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 |
* where PS must be at least 8 bytes with the value 0xFF. */ |
bad |= buf[1] ^ MBEDTLS_RSA_SIGN; |
/* Read the whole buffer. Set pad_done to nonzero if we find |
* the 0x00 byte and remember the padding length in pad_count. |
* If there's a non-0xff byte in the padding, the padding is bad. */ |
for( i = 2; i < ilen; i++ ) |
{ |
pad_done |= if_int( buf[i], 0, 1 ); |
pad_count += if_int( pad_done, 0, 1 ); |
bad |= if_int( pad_done, 0, buf[i] ^ 0xFF ); |
} |
} |
/* If pad_done is still zero, there's no data, only unfinished padding. */ |
bad |= if_int( pad_done, 0, 1 ); |
/* There must be at least 8 bytes of padding. */ |
bad |= size_greater_than( 8, pad_count ); |
/* If the padding is valid, set plaintext_size to the number of |
* remaining bytes after stripping the padding. If the padding |
* is invalid, avoid leaking this fact through the size of the |
* output: use the maximum message size that fits in the output |
* buffer. Do it without branches to avoid leaking the padding |
* validity through timing. RSA keys are small enough that all the |
* size_t values involved fit in unsigned int. */ |
plaintext_size = if_int( bad, |
(unsigned) plaintext_max_size, |
(unsigned) ( ilen - pad_count - 3 ) ); |
/* Set output_too_large to 0 if the plaintext fits in the output |
* buffer and to 1 otherwise. */ |
output_too_large = size_greater_than( plaintext_size, |
plaintext_max_size ); |
/* Set ret without branches to avoid timing attacks. Return: |
* - INVALID_PADDING if the padding is bad (bad != 0). |
* - OUTPUT_TOO_LARGE if the padding is good but the decrypted |
* plaintext does not fit in the output buffer. |
* - 0 if the padding is correct. */ |
ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, |
if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, |
0 ) ); |
/* If the padding is bad or the plaintext is too large, zero the |
* data that we're about to copy to the output buffer. |
* We need to copy the same amount of data |
* from the same buffer whether the padding is good or not to |
* avoid leaking the padding validity through overall timing or |
* through memory or cache access patterns. */ |
bad = all_or_nothing_int( bad | output_too_large ); |
for( i = 11; i < ilen; i++ ) |
buf[i] &= ~bad; |
/* If the plaintext is too large, truncate it to the buffer size. |
* Copy anyway to avoid revealing the length through timing, because |
* revealing the length is as bad as revealing the padding validity |
* for a Bleichenbacher attack. */ |
plaintext_size = if_int( output_too_large, |
(unsigned) plaintext_max_size, |
(unsigned) plaintext_size ); |
/* Move the plaintext to the leftmost position where it can start in |
* the working buffer, i.e. make it start plaintext_max_size from |
* the end of the buffer. Do this with a memory access trace that |
* does not depend on the plaintext size. After this move, the |
* starting location of the plaintext is no longer sensitive |
* information. */ |
mem_move_to_left( buf + ilen - plaintext_max_size, |
plaintext_max_size, |
plaintext_max_size - plaintext_size ); |
/* Finally copy the decrypted plaintext plus trailing zeros |
* into the output buffer. */ |
memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size ); |
/* Report the amount of data we copied to the output buffer. In case |
* of errors (bad padding or output too large), the value of *olen |
* when this function returns is not specified. Making it equivalent |
* to the good case limits the risks of leaking the padding validity. */ |
*olen = plaintext_size; |
cleanup: |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
return( ret ); |
} |
#endif /* MBEDTLS_PKCS1_V15 */ |
/* |
* Do an RSA operation, then remove the message padding |
*/ |
int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, size_t *olen, |
const unsigned char *input, |
unsigned char *output, |
size_t output_max_len) |
{ |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); |
RSA_VALIDATE_RET( input != NULL ); |
RSA_VALIDATE_RET( olen != NULL ); |
switch( ctx->padding ) |
{ |
#if defined(MBEDTLS_PKCS1_V15) |
case MBEDTLS_RSA_PKCS_V15: |
return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, |
input, output, output_max_len ); |
#endif |
#if defined(MBEDTLS_PKCS1_V21) |
case MBEDTLS_RSA_PKCS_V21: |
return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, |
olen, input, output, |
output_max_len ); |
#endif |
default: |
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); |
} |
} |
#if defined(MBEDTLS_PKCS1_V21) |
/* |
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function |
*/ |
int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
unsigned char *sig ) |
{ |
size_t olen; |
unsigned char *p = sig; |
unsigned char salt[MBEDTLS_MD_MAX_SIZE]; |
size_t slen, min_slen, hlen, offset = 0; |
int ret; |
size_t msb; |
const mbedtls_md_info_t *md_info; |
mbedtls_md_context_t md_ctx; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && |
hashlen == 0 ) || |
hash != NULL ); |
RSA_VALIDATE_RET( sig != NULL ); |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( f_rng == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
olen = ctx->len; |
if( md_alg != MBEDTLS_MD_NONE ) |
{ |
/* Gather length of hash to sign */ |
md_info = mbedtls_md_info_from_type( md_alg ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hashlen = mbedtls_md_get_size( md_info ); |
} |
md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hlen = mbedtls_md_get_size( md_info ); |
/* Calculate the largest possible salt length. Normally this is the hash |
* length, which is the maximum length the salt can have. If there is not |
* enough room, use the maximum salt length that fits. The constraint is |
* that the hash length plus the salt length plus 2 bytes must be at most |
* the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 |
* (PKCS#1 v2.2) §9.1.1 step 3. */ |
min_slen = hlen - 2; |
if( olen < hlen + min_slen + 2 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
else if( olen >= hlen + hlen + 2 ) |
slen = hlen; |
else |
slen = olen - hlen - 2; |
memset( sig, 0, olen ); |
/* Generate salt of length slen */ |
if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) |
return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); |
/* Note: EMSA-PSS encoding is over the length of N - 1 bits */ |
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; |
p += olen - hlen - slen - 2; |
*p++ = 0x01; |
memcpy( p, salt, slen ); |
p += slen; |
mbedtls_md_init( &md_ctx ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) |
goto exit; |
/* Generate H = Hash( M' ) */ |
if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) |
goto exit; |
/* Compensate for boundary condition when applying mask */ |
if( msb % 8 == 0 ) |
offset = 1; |
/* maskedDB: Apply dbMask to DB */ |
if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, |
&md_ctx ) ) != 0 ) |
goto exit; |
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; |
sig[0] &= 0xFF >> ( olen * 8 - msb ); |
p += hlen; |
*p++ = 0xBC; |
mbedtls_platform_zeroize( salt, sizeof( salt ) ); |
exit: |
mbedtls_md_free( &md_ctx ); |
if( ret != 0 ) |
return( ret ); |
return( ( mode == MBEDTLS_RSA_PUBLIC ) |
? mbedtls_rsa_public( ctx, sig, sig ) |
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); |
} |
#endif /* MBEDTLS_PKCS1_V21 */ |
#if defined(MBEDTLS_PKCS1_V15) |
/* |
* Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function |
*/ |
/* Construct a PKCS v1.5 encoding of a hashed message |
* |
* This is used both for signature generation and verification. |
* |
* Parameters: |
* - md_alg: Identifies the hash algorithm used to generate the given hash; |
* MBEDTLS_MD_NONE if raw data is signed. |
* - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. |
* - hash: Buffer containing the hashed message or the raw data. |
* - dst_len: Length of the encoded message. |
* - dst: Buffer to hold the encoded message. |
* |
* Assumptions: |
* - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. |
* - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. |
* - dst points to a buffer of size at least dst_len. |
* |
*/ |
static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
size_t dst_len, |
unsigned char *dst ) |
{ |
size_t oid_size = 0; |
size_t nb_pad = dst_len; |
unsigned char *p = dst; |
const char *oid = NULL; |
/* Are we signing hashed or raw data? */ |
if( md_alg != MBEDTLS_MD_NONE ) |
{ |
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hashlen = mbedtls_md_get_size( md_info ); |
/* Double-check that 8 + hashlen + oid_size can be used as a |
* 1-byte ASN.1 length encoding and that there's no overflow. */ |
if( 8 + hashlen + oid_size >= 0x80 || |
10 + hashlen < hashlen || |
10 + hashlen + oid_size < 10 + hashlen ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* |
* Static bounds check: |
* - Need 10 bytes for five tag-length pairs. |
* (Insist on 1-byte length encodings to protect against variants of |
* Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) |
* - Need hashlen bytes for hash |
* - Need oid_size bytes for hash alg OID. |
*/ |
if( nb_pad < 10 + hashlen + oid_size ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
nb_pad -= 10 + hashlen + oid_size; |
} |
else |
{ |
if( nb_pad < hashlen ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
nb_pad -= hashlen; |
} |
/* Need space for signature header and padding delimiter (3 bytes), |
* and 8 bytes for the minimal padding */ |
if( nb_pad < 3 + 8 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
nb_pad -= 3; |
/* Now nb_pad is the amount of memory to be filled |
* with padding, and at least 8 bytes long. */ |
/* Write signature header and padding */ |
*p++ = 0; |
*p++ = MBEDTLS_RSA_SIGN; |
memset( p, 0xFF, nb_pad ); |
p += nb_pad; |
*p++ = 0; |
/* Are we signing raw data? */ |
if( md_alg == MBEDTLS_MD_NONE ) |
{ |
memcpy( p, hash, hashlen ); |
return( 0 ); |
} |
/* Signing hashed data, add corresponding ASN.1 structure |
* |
* DigestInfo ::= SEQUENCE { |
* digestAlgorithm DigestAlgorithmIdentifier, |
* digest Digest } |
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier |
* Digest ::= OCTET STRING |
* |
* Schematic: |
* TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] |
* TAG-NULL + LEN [ NULL ] ] |
* TAG-OCTET + LEN [ HASH ] ] |
*/ |
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; |
*p++ = (unsigned char)( 0x08 + oid_size + hashlen ); |
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; |
*p++ = (unsigned char)( 0x04 + oid_size ); |
*p++ = MBEDTLS_ASN1_OID; |
*p++ = (unsigned char) oid_size; |
memcpy( p, oid, oid_size ); |
p += oid_size; |
*p++ = MBEDTLS_ASN1_NULL; |
*p++ = 0x00; |
*p++ = MBEDTLS_ASN1_OCTET_STRING; |
*p++ = (unsigned char) hashlen; |
memcpy( p, hash, hashlen ); |
p += hashlen; |
/* Just a sanity-check, should be automatic |
* after the initial bounds check. */ |
if( p != dst + dst_len ) |
{ |
mbedtls_platform_zeroize( dst, dst_len ); |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
} |
return( 0 ); |
} |
/* |
* Do an RSA operation to sign the message digest |
*/ |
int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
unsigned char *sig ) |
{ |
int ret; |
unsigned char *sig_try = NULL, *verif = NULL; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && |
hashlen == 0 ) || |
hash != NULL ); |
RSA_VALIDATE_RET( sig != NULL ); |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* |
* Prepare PKCS1-v1.5 encoding (padding and hash identifier) |
*/ |
if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, |
ctx->len, sig ) ) != 0 ) |
return( ret ); |
/* |
* Call respective RSA primitive |
*/ |
if( mode == MBEDTLS_RSA_PUBLIC ) |
{ |
/* Skip verification on a public key operation */ |
return( mbedtls_rsa_public( ctx, sig, sig ) ); |
} |
/* Private key operation |
* |
* In order to prevent Lenstra's attack, make the signature in a |
* temporary buffer and check it before returning it. |
*/ |
sig_try = mbedtls_calloc( 1, ctx->len ); |
if( sig_try == NULL ) |
return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); |
verif = mbedtls_calloc( 1, ctx->len ); |
if( verif == NULL ) |
{ |
mbedtls_free( sig_try ); |
return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); |
} |
MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); |
MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); |
if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; |
goto cleanup; |
} |
memcpy( sig, sig_try, ctx->len ); |
cleanup: |
mbedtls_free( sig_try ); |
mbedtls_free( verif ); |
return( ret ); |
} |
#endif /* MBEDTLS_PKCS1_V15 */ |
/* |
* Do an RSA operation to sign the message digest |
*/ |
int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
unsigned char *sig ) |
{ |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && |
hashlen == 0 ) || |
hash != NULL ); |
RSA_VALIDATE_RET( sig != NULL ); |
switch( ctx->padding ) |
{ |
#if defined(MBEDTLS_PKCS1_V15) |
case MBEDTLS_RSA_PKCS_V15: |
return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, |
hashlen, hash, sig ); |
#endif |
#if defined(MBEDTLS_PKCS1_V21) |
case MBEDTLS_RSA_PKCS_V21: |
return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, |
hashlen, hash, sig ); |
#endif |
default: |
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); |
} |
} |
#if defined(MBEDTLS_PKCS1_V21) |
/* |
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function |
*/ |
int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
mbedtls_md_type_t mgf1_hash_id, |
int expected_salt_len, |
const unsigned char *sig ) |
{ |
int ret; |
size_t siglen; |
unsigned char *p; |
unsigned char *hash_start; |
unsigned char result[MBEDTLS_MD_MAX_SIZE]; |
unsigned char zeros[8]; |
unsigned int hlen; |
size_t observed_salt_len, msb; |
const mbedtls_md_info_t *md_info; |
mbedtls_md_context_t md_ctx; |
unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( sig != NULL ); |
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && |
hashlen == 0 ) || |
hash != NULL ); |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
siglen = ctx->len; |
if( siglen < 16 || siglen > sizeof( buf ) ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
ret = ( mode == MBEDTLS_RSA_PUBLIC ) |
? mbedtls_rsa_public( ctx, sig, buf ) |
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); |
if( ret != 0 ) |
return( ret ); |
p = buf; |
if( buf[siglen - 1] != 0xBC ) |
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); |
if( md_alg != MBEDTLS_MD_NONE ) |
{ |
/* Gather length of hash to sign */ |
md_info = mbedtls_md_info_from_type( md_alg ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hashlen = mbedtls_md_get_size( md_info ); |
} |
md_info = mbedtls_md_info_from_type( mgf1_hash_id ); |
if( md_info == NULL ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hlen = mbedtls_md_get_size( md_info ); |
memset( zeros, 0, 8 ); |
/* |
* Note: EMSA-PSS verification is over the length of N - 1 bits |
*/ |
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; |
if( buf[0] >> ( 8 - siglen * 8 + msb ) ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* Compensate for boundary condition when applying mask */ |
if( msb % 8 == 0 ) |
{ |
p++; |
siglen -= 1; |
} |
if( siglen < hlen + 2 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
hash_start = p + siglen - hlen - 1; |
mbedtls_md_init( &md_ctx ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) |
goto exit; |
ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); |
if( ret != 0 ) |
goto exit; |
buf[0] &= 0xFF >> ( siglen * 8 - msb ); |
while( p < hash_start - 1 && *p == 0 ) |
p++; |
if( *p++ != 0x01 ) |
{ |
ret = MBEDTLS_ERR_RSA_INVALID_PADDING; |
goto exit; |
} |
observed_salt_len = hash_start - p; |
if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && |
observed_salt_len != (size_t) expected_salt_len ) |
{ |
ret = MBEDTLS_ERR_RSA_INVALID_PADDING; |
goto exit; |
} |
/* |
* Generate H = Hash( M' ) |
*/ |
ret = mbedtls_md_starts( &md_ctx ); |
if ( ret != 0 ) |
goto exit; |
ret = mbedtls_md_update( &md_ctx, zeros, 8 ); |
if ( ret != 0 ) |
goto exit; |
ret = mbedtls_md_update( &md_ctx, hash, hashlen ); |
if ( ret != 0 ) |
goto exit; |
ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); |
if ( ret != 0 ) |
goto exit; |
ret = mbedtls_md_finish( &md_ctx, result ); |
if ( ret != 0 ) |
goto exit; |
if( memcmp( hash_start, result, hlen ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; |
goto exit; |
} |
exit: |
mbedtls_md_free( &md_ctx ); |
return( ret ); |
} |
/* |
* Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function |
*/ |
int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
const unsigned char *sig ) |
{ |
mbedtls_md_type_t mgf1_hash_id; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( sig != NULL ); |
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && |
hashlen == 0 ) || |
hash != NULL ); |
mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) |
? (mbedtls_md_type_t) ctx->hash_id |
: md_alg; |
return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, |
md_alg, hashlen, hash, |
mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, |
sig ) ); |
} |
#endif /* MBEDTLS_PKCS1_V21 */ |
#if defined(MBEDTLS_PKCS1_V15) |
/* |
* Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function |
*/ |
int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
const unsigned char *sig ) |
{ |
int ret = 0; |
size_t sig_len; |
unsigned char *encoded = NULL, *encoded_expected = NULL; |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( sig != NULL ); |
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && |
hashlen == 0 ) || |
hash != NULL ); |
sig_len = ctx->len; |
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) |
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); |
/* |
* Prepare expected PKCS1 v1.5 encoding of hash. |
*/ |
if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || |
( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) |
{ |
ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; |
goto cleanup; |
} |
if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, |
encoded_expected ) ) != 0 ) |
goto cleanup; |
/* |
* Apply RSA primitive to get what should be PKCS1 encoded hash. |
*/ |
ret = ( mode == MBEDTLS_RSA_PUBLIC ) |
? mbedtls_rsa_public( ctx, sig, encoded ) |
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); |
if( ret != 0 ) |
goto cleanup; |
/* |
* Compare |
*/ |
if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, |
sig_len ) ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; |
goto cleanup; |
} |
cleanup: |
if( encoded != NULL ) |
{ |
mbedtls_platform_zeroize( encoded, sig_len ); |
mbedtls_free( encoded ); |
} |
if( encoded_expected != NULL ) |
{ |
mbedtls_platform_zeroize( encoded_expected, sig_len ); |
mbedtls_free( encoded_expected ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_PKCS1_V15 */ |
/* |
* Do an RSA operation and check the message digest |
*/ |
int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng, |
int mode, |
mbedtls_md_type_t md_alg, |
unsigned int hashlen, |
const unsigned char *hash, |
const unsigned char *sig ) |
{ |
RSA_VALIDATE_RET( ctx != NULL ); |
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || |
mode == MBEDTLS_RSA_PUBLIC ); |
RSA_VALIDATE_RET( sig != NULL ); |
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && |
hashlen == 0 ) || |
hash != NULL ); |
switch( ctx->padding ) |
{ |
#if defined(MBEDTLS_PKCS1_V15) |
case MBEDTLS_RSA_PKCS_V15: |
return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, |
hashlen, hash, sig ); |
#endif |
#if defined(MBEDTLS_PKCS1_V21) |
case MBEDTLS_RSA_PKCS_V21: |
return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, |
hashlen, hash, sig ); |
#endif |
default: |
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); |
} |
} |
/* |
* Copy the components of an RSA key |
*/ |
int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) |
{ |
int ret; |
RSA_VALIDATE_RET( dst != NULL ); |
RSA_VALIDATE_RET( src != NULL ); |
dst->ver = src->ver; |
dst->len = src->len; |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); |
#if !defined(MBEDTLS_RSA_NO_CRT) |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); |
#endif |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); |
dst->padding = src->padding; |
dst->hash_id = src->hash_id; |
cleanup: |
if( ret != 0 ) |
mbedtls_rsa_free( dst ); |
return( ret ); |
} |
/* |
* Free the components of an RSA key |
*/ |
void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_mpi_free( &ctx->Vi ); |
mbedtls_mpi_free( &ctx->Vf ); |
mbedtls_mpi_free( &ctx->RN ); |
mbedtls_mpi_free( &ctx->D ); |
mbedtls_mpi_free( &ctx->Q ); |
mbedtls_mpi_free( &ctx->P ); |
mbedtls_mpi_free( &ctx->E ); |
mbedtls_mpi_free( &ctx->N ); |
#if !defined(MBEDTLS_RSA_NO_CRT) |
mbedtls_mpi_free( &ctx->RQ ); |
mbedtls_mpi_free( &ctx->RP ); |
mbedtls_mpi_free( &ctx->QP ); |
mbedtls_mpi_free( &ctx->DQ ); |
mbedtls_mpi_free( &ctx->DP ); |
#endif /* MBEDTLS_RSA_NO_CRT */ |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &ctx->mutex ); |
#endif |
} |
#endif /* !MBEDTLS_RSA_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
#include "mbedtls/sha1.h" |
/* |
* Example RSA-1024 keypair, for test purposes |
*/ |
#define KEY_LEN 128 |
#define RSA_N "9292758453063D803DD603D5E777D788" \ |
"8ED1D5BF35786190FA2F23EBC0848AEA" \ |
"DDA92CA6C3D80B32C4D109BE0F36D6AE" \ |
"7130B9CED7ACDF54CFC7555AC14EEBAB" \ |
"93A89813FBF3C4F8066D2D800F7C38A8" \ |
"1AE31942917403FF4946B0A83D3D3E05" \ |
"EE57C6F5F5606FB5D4BC6CD34EE0801A" \ |
"5E94BB77B07507233A0BC7BAC8F90F79" |
#define RSA_E "10001" |
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ |
"66CA472BC44D253102F8B4A9D3BFA750" \ |
"91386C0077937FE33FA3252D28855837" \ |
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \ |
"DF79C5CE07EE72C7F123142198164234" \ |
"CABB724CF78B8173B9F880FC86322407" \ |
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \ |
"071513A1E85B5DFA031F21ECAE91A34D" |
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ |
"2C01CAD19EA484A87EA4377637E75500" \ |
"FCB2005C5C7DD6EC4AC023CDA285D796" \ |
"C3D9E75E1EFC42488BB4F1D13AC30A57" |
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ |
"E211C2B9E5DB1ED0BF61D0D9899620F4" \ |
"910E4168387E3C30AA1E00C339A79508" \ |
"8452DD96A9A5EA5D9DCA68DA636032AF" |
#define PT_LEN 24 |
#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ |
"\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" |
#if defined(MBEDTLS_PKCS1_V15) |
static int myrand( void *rng_state, unsigned char *output, size_t len ) |
{ |
#if !defined(__OpenBSD__) |
size_t i; |
if( rng_state != NULL ) |
rng_state = NULL; |
for( i = 0; i < len; ++i ) |
output[i] = rand(); |
#else |
if( rng_state != NULL ) |
rng_state = NULL; |
arc4random_buf( output, len ); |
#endif /* !OpenBSD */ |
return( 0 ); |
} |
#endif /* MBEDTLS_PKCS1_V15 */ |
/* |
* Checkup routine |
*/ |
int mbedtls_rsa_self_test( int verbose ) |
{ |
int ret = 0; |
#if defined(MBEDTLS_PKCS1_V15) |
size_t len; |
mbedtls_rsa_context rsa; |
unsigned char rsa_plaintext[PT_LEN]; |
unsigned char rsa_decrypted[PT_LEN]; |
unsigned char rsa_ciphertext[KEY_LEN]; |
#if defined(MBEDTLS_SHA1_C) |
unsigned char sha1sum[20]; |
#endif |
mbedtls_mpi K; |
mbedtls_mpi_init( &K ); |
mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); |
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); |
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); |
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); |
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); |
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); |
MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); |
if( verbose != 0 ) |
mbedtls_printf( " RSA key validation: " ); |
if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || |
mbedtls_rsa_check_privkey( &rsa ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n PKCS#1 encryption : " ); |
memcpy( rsa_plaintext, RSA_PT, PT_LEN ); |
if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, |
PT_LEN, rsa_plaintext, |
rsa_ciphertext ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n PKCS#1 decryption : " ); |
if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, |
&len, rsa_ciphertext, rsa_decrypted, |
sizeof(rsa_decrypted) ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
#if defined(MBEDTLS_SHA1_C) |
if( verbose != 0 ) |
mbedtls_printf( " PKCS#1 data sign : " ); |
if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
return( 1 ); |
} |
if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, |
MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, |
sha1sum, rsa_ciphertext ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); |
if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, |
MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, |
sha1sum, rsa_ciphertext ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
#endif /* MBEDTLS_SHA1_C */ |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
cleanup: |
mbedtls_mpi_free( &K ); |
mbedtls_rsa_free( &rsa ); |
#else /* MBEDTLS_PKCS1_V15 */ |
((void) verbose); |
#endif /* MBEDTLS_PKCS1_V15 */ |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_RSA_C */ |
/programs/develop/libraries/kos_mbedtls/library/rsa_internal.c |
---|
0,0 → 1,494 |
/* |
* Helper functions for the RSA module |
* |
* Copyright (C) 2006-2017, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
* |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_RSA_C) |
#include "mbedtls/rsa.h" |
#include "mbedtls/bignum.h" |
#include "mbedtls/rsa_internal.h" |
/* |
* Compute RSA prime factors from public and private exponents |
* |
* Summary of algorithm: |
* Setting F := lcm(P-1,Q-1), the idea is as follows: |
* |
* (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) |
* is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the |
* square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four |
* possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) |
* or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime |
* factors of N. |
* |
* (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same |
* construction still applies since (-)^K is the identity on the set of |
* roots of 1 in Z/NZ. |
* |
* The public and private key primitives (-)^E and (-)^D are mutually inverse |
* bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. |
* if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. |
* Splitting L = 2^t * K with K odd, we have |
* |
* DE - 1 = FL = (F/2) * (2^(t+1)) * K, |
* |
* so (F / 2) * K is among the numbers |
* |
* (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord |
* |
* where ord is the order of 2 in (DE - 1). |
* We can therefore iterate through these numbers apply the construction |
* of (a) and (b) above to attempt to factor N. |
* |
*/ |
int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, |
mbedtls_mpi const *E, mbedtls_mpi const *D, |
mbedtls_mpi *P, mbedtls_mpi *Q ) |
{ |
int ret = 0; |
uint16_t attempt; /* Number of current attempt */ |
uint16_t iter; /* Number of squares computed in the current attempt */ |
uint16_t order; /* Order of 2 in DE - 1 */ |
mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ |
mbedtls_mpi K; /* Temporary holding the current candidate */ |
const unsigned char primes[] = { 2, |
3, 5, 7, 11, 13, 17, 19, 23, |
29, 31, 37, 41, 43, 47, 53, 59, |
61, 67, 71, 73, 79, 83, 89, 97, |
101, 103, 107, 109, 113, 127, 131, 137, |
139, 149, 151, 157, 163, 167, 173, 179, |
181, 191, 193, 197, 199, 211, 223, 227, |
229, 233, 239, 241, 251 |
}; |
const size_t num_primes = sizeof( primes ) / sizeof( *primes ); |
if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || |
mbedtls_mpi_cmp_int( D, 1 ) <= 0 || |
mbedtls_mpi_cmp_mpi( D, N ) >= 0 || |
mbedtls_mpi_cmp_int( E, 1 ) <= 0 || |
mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) |
{ |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
} |
/* |
* Initializations and temporary changes |
*/ |
mbedtls_mpi_init( &K ); |
mbedtls_mpi_init( &T ); |
/* T := DE - 1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); |
if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) |
{ |
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; |
goto cleanup; |
} |
/* After this operation, T holds the largest odd divisor of DE - 1. */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); |
/* |
* Actual work |
*/ |
/* Skip trying 2 if N == 1 mod 8 */ |
attempt = 0; |
if( N->p[0] % 8 == 1 ) |
attempt = 1; |
for( ; attempt < num_primes; ++attempt ) |
{ |
mbedtls_mpi_lset( &K, primes[attempt] ); |
/* Check if gcd(K,N) = 1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); |
if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) |
continue; |
/* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... |
* and check whether they have nontrivial GCD with N. */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, |
Q /* temporarily use Q for storing Montgomery |
* multiplication helper values */ ) ); |
for( iter = 1; iter <= order; ++iter ) |
{ |
/* If we reach 1 prematurely, there's no point |
* in continuing to square K */ |
if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) |
break; |
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); |
if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && |
mbedtls_mpi_cmp_mpi( P, N ) == -1 ) |
{ |
/* |
* Have found a nontrivial divisor P of N. |
* Set Q := N / P. |
*/ |
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); |
} |
/* |
* If we get here, then either we prematurely aborted the loop because |
* we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must |
* be 1 if D,E,N were consistent. |
* Check if that's the case and abort if not, to avoid very long, |
* yet eventually failing, computations if N,D,E were not sane. |
*/ |
if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) |
{ |
break; |
} |
} |
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; |
cleanup: |
mbedtls_mpi_free( &K ); |
mbedtls_mpi_free( &T ); |
return( ret ); |
} |
/* |
* Given P, Q and the public exponent E, deduce D. |
* This is essentially a modular inversion. |
*/ |
int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, |
mbedtls_mpi const *Q, |
mbedtls_mpi const *E, |
mbedtls_mpi *D ) |
{ |
int ret = 0; |
mbedtls_mpi K, L; |
if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || |
mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || |
mbedtls_mpi_cmp_int( E, 0 ) == 0 ) |
{ |
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); |
} |
mbedtls_mpi_init( &K ); |
mbedtls_mpi_init( &L ); |
/* Temporarily put K := P-1 and L := Q-1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); |
/* Temporarily put D := gcd(P-1, Q-1) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); |
/* K := LCM(P-1, Q-1) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); |
/* Compute modular inverse of E in LCM(P-1, Q-1) */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); |
cleanup: |
mbedtls_mpi_free( &K ); |
mbedtls_mpi_free( &L ); |
return( ret ); |
} |
/* |
* Check that RSA CRT parameters are in accordance with core parameters. |
*/ |
int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, |
const mbedtls_mpi *D, const mbedtls_mpi *DP, |
const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) |
{ |
int ret = 0; |
mbedtls_mpi K, L; |
mbedtls_mpi_init( &K ); |
mbedtls_mpi_init( &L ); |
/* Check that DP - D == 0 mod P - 1 */ |
if( DP != NULL ) |
{ |
if( P == NULL ) |
{ |
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); |
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
} |
/* Check that DQ - D == 0 mod Q - 1 */ |
if( DQ != NULL ) |
{ |
if( Q == NULL ) |
{ |
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); |
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
} |
/* Check that QP * Q - 1 == 0 mod P */ |
if( QP != NULL ) |
{ |
if( P == NULL || Q == NULL ) |
{ |
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
goto cleanup; |
} |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); |
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
} |
cleanup: |
/* Wrap MPI error codes by RSA check failure error code */ |
if( ret != 0 && |
ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && |
ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) |
{ |
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
} |
mbedtls_mpi_free( &K ); |
mbedtls_mpi_free( &L ); |
return( ret ); |
} |
/* |
* Check that core RSA parameters are sane. |
*/ |
int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, |
const mbedtls_mpi *Q, const mbedtls_mpi *D, |
const mbedtls_mpi *E, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret = 0; |
mbedtls_mpi K, L; |
mbedtls_mpi_init( &K ); |
mbedtls_mpi_init( &L ); |
/* |
* Step 1: If PRNG provided, check that P and Q are prime |
*/ |
#if defined(MBEDTLS_GENPRIME) |
/* |
* When generating keys, the strongest security we support aims for an error |
* rate of at most 2^-100 and we are aiming for the same certainty here as |
* well. |
*/ |
if( f_rng != NULL && P != NULL && |
( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
if( f_rng != NULL && Q != NULL && |
( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
#else |
((void) f_rng); |
((void) p_rng); |
#endif /* MBEDTLS_GENPRIME */ |
/* |
* Step 2: Check that 1 < N = P * Q |
*/ |
if( P != NULL && Q != NULL && N != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); |
if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || |
mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
} |
/* |
* Step 3: Check and 1 < D, E < N if present. |
*/ |
if( N != NULL && D != NULL && E != NULL ) |
{ |
if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || |
mbedtls_mpi_cmp_int( E, 1 ) <= 0 || |
mbedtls_mpi_cmp_mpi( D, N ) >= 0 || |
mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
} |
/* |
* Step 4: Check that D, E are inverse modulo P-1 and Q-1 |
*/ |
if( P != NULL && Q != NULL && D != NULL && E != NULL ) |
{ |
if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || |
mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
/* Compute DE-1 mod P-1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); |
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
/* Compute DE-1 mod Q-1 */ |
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); |
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) |
{ |
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
goto cleanup; |
} |
} |
cleanup: |
mbedtls_mpi_free( &K ); |
mbedtls_mpi_free( &L ); |
/* Wrap MPI error codes by RSA check failure error code */ |
if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) |
{ |
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
} |
return( ret ); |
} |
int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, |
const mbedtls_mpi *D, mbedtls_mpi *DP, |
mbedtls_mpi *DQ, mbedtls_mpi *QP ) |
{ |
int ret = 0; |
mbedtls_mpi K; |
mbedtls_mpi_init( &K ); |
/* DP = D mod P-1 */ |
if( DP != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); |
} |
/* DQ = D mod Q-1 */ |
if( DQ != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); |
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); |
} |
/* QP = Q^{-1} mod P */ |
if( QP != NULL ) |
{ |
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); |
} |
cleanup: |
mbedtls_mpi_free( &K ); |
return( ret ); |
} |
#endif /* MBEDTLS_RSA_C */ |
/programs/develop/libraries/kos_mbedtls/library/sha1.c |
---|
0,0 → 1,575 |
/* |
* FIPS-180-1 compliant SHA-1 implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The SHA-1 standard was published by NIST in 1993. |
* |
* http://www.itl.nist.gov/fipspubs/fip180-1.htm |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SHA1_C) |
#include "mbedtls/sha1.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#define SHA1_VALIDATE_RET(cond) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) |
#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if !defined(MBEDTLS_SHA1_ALT) |
/* |
* 32-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} |
#endif |
void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) |
{ |
SHA1_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); |
} |
void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); |
} |
void mbedtls_sha1_clone( mbedtls_sha1_context *dst, |
const mbedtls_sha1_context *src ) |
{ |
SHA1_VALIDATE( dst != NULL ); |
SHA1_VALIDATE( src != NULL ); |
*dst = *src; |
} |
/* |
* SHA-1 context setup |
*/ |
int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) |
{ |
SHA1_VALIDATE_RET( ctx != NULL ); |
ctx->total[0] = 0; |
ctx->total[1] = 0; |
ctx->state[0] = 0x67452301; |
ctx->state[1] = 0xEFCDAB89; |
ctx->state[2] = 0x98BADCFE; |
ctx->state[3] = 0x10325476; |
ctx->state[4] = 0xC3D2E1F0; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) |
{ |
mbedtls_sha1_starts_ret( ctx ); |
} |
#endif |
#if !defined(MBEDTLS_SHA1_PROCESS_ALT) |
int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, |
const unsigned char data[64] ) |
{ |
uint32_t temp, W[16], A, B, C, D, E; |
SHA1_VALIDATE_RET( ctx != NULL ); |
SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); |
GET_UINT32_BE( W[ 0], data, 0 ); |
GET_UINT32_BE( W[ 1], data, 4 ); |
GET_UINT32_BE( W[ 2], data, 8 ); |
GET_UINT32_BE( W[ 3], data, 12 ); |
GET_UINT32_BE( W[ 4], data, 16 ); |
GET_UINT32_BE( W[ 5], data, 20 ); |
GET_UINT32_BE( W[ 6], data, 24 ); |
GET_UINT32_BE( W[ 7], data, 28 ); |
GET_UINT32_BE( W[ 8], data, 32 ); |
GET_UINT32_BE( W[ 9], data, 36 ); |
GET_UINT32_BE( W[10], data, 40 ); |
GET_UINT32_BE( W[11], data, 44 ); |
GET_UINT32_BE( W[12], data, 48 ); |
GET_UINT32_BE( W[13], data, 52 ); |
GET_UINT32_BE( W[14], data, 56 ); |
GET_UINT32_BE( W[15], data, 60 ); |
#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) |
#define R(t) \ |
( \ |
temp = W[( (t) - 3 ) & 0x0F] ^ W[( (t) - 8 ) & 0x0F] ^ \ |
W[( (t) - 14 ) & 0x0F] ^ W[ (t) & 0x0F], \ |
( W[(t) & 0x0F] = S(temp,1) ) \ |
) |
#define P(a,b,c,d,e,x) \ |
do \ |
{ \ |
(e) += S((a),5) + F((b),(c),(d)) + K + (x); \ |
(b) = S((b),30); \ |
} while( 0 ) |
A = ctx->state[0]; |
B = ctx->state[1]; |
C = ctx->state[2]; |
D = ctx->state[3]; |
E = ctx->state[4]; |
#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) |
#define K 0x5A827999 |
P( A, B, C, D, E, W[0] ); |
P( E, A, B, C, D, W[1] ); |
P( D, E, A, B, C, W[2] ); |
P( C, D, E, A, B, W[3] ); |
P( B, C, D, E, A, W[4] ); |
P( A, B, C, D, E, W[5] ); |
P( E, A, B, C, D, W[6] ); |
P( D, E, A, B, C, W[7] ); |
P( C, D, E, A, B, W[8] ); |
P( B, C, D, E, A, W[9] ); |
P( A, B, C, D, E, W[10] ); |
P( E, A, B, C, D, W[11] ); |
P( D, E, A, B, C, W[12] ); |
P( C, D, E, A, B, W[13] ); |
P( B, C, D, E, A, W[14] ); |
P( A, B, C, D, E, W[15] ); |
P( E, A, B, C, D, R(16) ); |
P( D, E, A, B, C, R(17) ); |
P( C, D, E, A, B, R(18) ); |
P( B, C, D, E, A, R(19) ); |
#undef K |
#undef F |
#define F(x,y,z) ((x) ^ (y) ^ (z)) |
#define K 0x6ED9EBA1 |
P( A, B, C, D, E, R(20) ); |
P( E, A, B, C, D, R(21) ); |
P( D, E, A, B, C, R(22) ); |
P( C, D, E, A, B, R(23) ); |
P( B, C, D, E, A, R(24) ); |
P( A, B, C, D, E, R(25) ); |
P( E, A, B, C, D, R(26) ); |
P( D, E, A, B, C, R(27) ); |
P( C, D, E, A, B, R(28) ); |
P( B, C, D, E, A, R(29) ); |
P( A, B, C, D, E, R(30) ); |
P( E, A, B, C, D, R(31) ); |
P( D, E, A, B, C, R(32) ); |
P( C, D, E, A, B, R(33) ); |
P( B, C, D, E, A, R(34) ); |
P( A, B, C, D, E, R(35) ); |
P( E, A, B, C, D, R(36) ); |
P( D, E, A, B, C, R(37) ); |
P( C, D, E, A, B, R(38) ); |
P( B, C, D, E, A, R(39) ); |
#undef K |
#undef F |
#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) |
#define K 0x8F1BBCDC |
P( A, B, C, D, E, R(40) ); |
P( E, A, B, C, D, R(41) ); |
P( D, E, A, B, C, R(42) ); |
P( C, D, E, A, B, R(43) ); |
P( B, C, D, E, A, R(44) ); |
P( A, B, C, D, E, R(45) ); |
P( E, A, B, C, D, R(46) ); |
P( D, E, A, B, C, R(47) ); |
P( C, D, E, A, B, R(48) ); |
P( B, C, D, E, A, R(49) ); |
P( A, B, C, D, E, R(50) ); |
P( E, A, B, C, D, R(51) ); |
P( D, E, A, B, C, R(52) ); |
P( C, D, E, A, B, R(53) ); |
P( B, C, D, E, A, R(54) ); |
P( A, B, C, D, E, R(55) ); |
P( E, A, B, C, D, R(56) ); |
P( D, E, A, B, C, R(57) ); |
P( C, D, E, A, B, R(58) ); |
P( B, C, D, E, A, R(59) ); |
#undef K |
#undef F |
#define F(x,y,z) ((x) ^ (y) ^ (z)) |
#define K 0xCA62C1D6 |
P( A, B, C, D, E, R(60) ); |
P( E, A, B, C, D, R(61) ); |
P( D, E, A, B, C, R(62) ); |
P( C, D, E, A, B, R(63) ); |
P( B, C, D, E, A, R(64) ); |
P( A, B, C, D, E, R(65) ); |
P( E, A, B, C, D, R(66) ); |
P( D, E, A, B, C, R(67) ); |
P( C, D, E, A, B, R(68) ); |
P( B, C, D, E, A, R(69) ); |
P( A, B, C, D, E, R(70) ); |
P( E, A, B, C, D, R(71) ); |
P( D, E, A, B, C, R(72) ); |
P( C, D, E, A, B, R(73) ); |
P( B, C, D, E, A, R(74) ); |
P( A, B, C, D, E, R(75) ); |
P( E, A, B, C, D, R(76) ); |
P( D, E, A, B, C, R(77) ); |
P( C, D, E, A, B, R(78) ); |
P( B, C, D, E, A, R(79) ); |
#undef K |
#undef F |
ctx->state[0] += A; |
ctx->state[1] += B; |
ctx->state[2] += C; |
ctx->state[3] += D; |
ctx->state[4] += E; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, |
const unsigned char data[64] ) |
{ |
mbedtls_internal_sha1_process( ctx, data ); |
} |
#endif |
#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ |
/* |
* SHA-1 process buffer |
*/ |
int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
int ret; |
size_t fill; |
uint32_t left; |
SHA1_VALIDATE_RET( ctx != NULL ); |
SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); |
if( ilen == 0 ) |
return( 0 ); |
left = ctx->total[0] & 0x3F; |
fill = 64 - left; |
ctx->total[0] += (uint32_t) ilen; |
ctx->total[0] &= 0xFFFFFFFF; |
if( ctx->total[0] < (uint32_t) ilen ) |
ctx->total[1]++; |
if( left && ilen >= fill ) |
{ |
memcpy( (void *) (ctx->buffer + left), input, fill ); |
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
input += fill; |
ilen -= fill; |
left = 0; |
} |
while( ilen >= 64 ) |
{ |
if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) |
return( ret ); |
input += 64; |
ilen -= 64; |
} |
if( ilen > 0 ) |
memcpy( (void *) (ctx->buffer + left), input, ilen ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
mbedtls_sha1_update_ret( ctx, input, ilen ); |
} |
#endif |
/* |
* SHA-1 final digest |
*/ |
int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, |
unsigned char output[20] ) |
{ |
int ret; |
uint32_t used; |
uint32_t high, low; |
SHA1_VALIDATE_RET( ctx != NULL ); |
SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); |
/* |
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length |
*/ |
used = ctx->total[0] & 0x3F; |
ctx->buffer[used++] = 0x80; |
if( used <= 56 ) |
{ |
/* Enough room for padding + length in current block */ |
memset( ctx->buffer + used, 0, 56 - used ); |
} |
else |
{ |
/* We'll need an extra block */ |
memset( ctx->buffer + used, 0, 64 - used ); |
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
memset( ctx->buffer, 0, 56 ); |
} |
/* |
* Add message length |
*/ |
high = ( ctx->total[0] >> 29 ) |
| ( ctx->total[1] << 3 ); |
low = ( ctx->total[0] << 3 ); |
PUT_UINT32_BE( high, ctx->buffer, 56 ); |
PUT_UINT32_BE( low, ctx->buffer, 60 ); |
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
/* |
* Output final state |
*/ |
PUT_UINT32_BE( ctx->state[0], output, 0 ); |
PUT_UINT32_BE( ctx->state[1], output, 4 ); |
PUT_UINT32_BE( ctx->state[2], output, 8 ); |
PUT_UINT32_BE( ctx->state[3], output, 12 ); |
PUT_UINT32_BE( ctx->state[4], output, 16 ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, |
unsigned char output[20] ) |
{ |
mbedtls_sha1_finish_ret( ctx, output ); |
} |
#endif |
#endif /* !MBEDTLS_SHA1_ALT */ |
/* |
* output = SHA-1( input buffer ) |
*/ |
int mbedtls_sha1_ret( const unsigned char *input, |
size_t ilen, |
unsigned char output[20] ) |
{ |
int ret; |
mbedtls_sha1_context ctx; |
SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); |
SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); |
mbedtls_sha1_init( &ctx ); |
if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_sha1_free( &ctx ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha1( const unsigned char *input, |
size_t ilen, |
unsigned char output[20] ) |
{ |
mbedtls_sha1_ret( input, ilen, output ); |
} |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* FIPS-180-1 test vectors |
*/ |
static const unsigned char sha1_test_buf[3][57] = |
{ |
{ "abc" }, |
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, |
{ "" } |
}; |
static const size_t sha1_test_buflen[3] = |
{ |
3, 56, 1000 |
}; |
static const unsigned char sha1_test_sum[3][20] = |
{ |
{ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, |
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, |
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, |
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, |
{ 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, |
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_sha1_self_test( int verbose ) |
{ |
int i, j, buflen, ret = 0; |
unsigned char buf[1024]; |
unsigned char sha1sum[20]; |
mbedtls_sha1_context ctx; |
mbedtls_sha1_init( &ctx ); |
/* |
* SHA-1 |
*/ |
for( i = 0; i < 3; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); |
if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) |
goto fail; |
if( i == 2 ) |
{ |
memset( buf, 'a', buflen = 1000 ); |
for( j = 0; j < 1000; j++ ) |
{ |
ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); |
if( ret != 0 ) |
goto fail; |
} |
} |
else |
{ |
ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], |
sha1_test_buflen[i] ); |
if( ret != 0 ) |
goto fail; |
} |
if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) |
goto fail; |
if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) |
{ |
ret = 1; |
goto fail; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
goto exit; |
fail: |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
exit: |
mbedtls_sha1_free( &ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_SHA1_C */ |
/programs/develop/libraries/kos_mbedtls/library/sha256.c |
---|
0,0 → 1,588 |
/* |
* FIPS-180-2 compliant SHA-256 implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The SHA-256 Secure Hash Standard was published by NIST in 2002. |
* |
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SHA256_C) |
#include "mbedtls/sha256.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#include <stdlib.h> |
#define mbedtls_printf printf |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#define SHA256_VALIDATE_RET(cond) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) |
#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if !defined(MBEDTLS_SHA256_ALT) |
/* |
* 32-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
do { \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} while( 0 ) |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
do { \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} while( 0 ) |
#endif |
void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) |
{ |
SHA256_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); |
} |
void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); |
} |
void mbedtls_sha256_clone( mbedtls_sha256_context *dst, |
const mbedtls_sha256_context *src ) |
{ |
SHA256_VALIDATE( dst != NULL ); |
SHA256_VALIDATE( src != NULL ); |
*dst = *src; |
} |
/* |
* SHA-256 context setup |
*/ |
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) |
{ |
SHA256_VALIDATE_RET( ctx != NULL ); |
SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); |
ctx->total[0] = 0; |
ctx->total[1] = 0; |
if( is224 == 0 ) |
{ |
/* SHA-256 */ |
ctx->state[0] = 0x6A09E667; |
ctx->state[1] = 0xBB67AE85; |
ctx->state[2] = 0x3C6EF372; |
ctx->state[3] = 0xA54FF53A; |
ctx->state[4] = 0x510E527F; |
ctx->state[5] = 0x9B05688C; |
ctx->state[6] = 0x1F83D9AB; |
ctx->state[7] = 0x5BE0CD19; |
} |
else |
{ |
/* SHA-224 */ |
ctx->state[0] = 0xC1059ED8; |
ctx->state[1] = 0x367CD507; |
ctx->state[2] = 0x3070DD17; |
ctx->state[3] = 0xF70E5939; |
ctx->state[4] = 0xFFC00B31; |
ctx->state[5] = 0x68581511; |
ctx->state[6] = 0x64F98FA7; |
ctx->state[7] = 0xBEFA4FA4; |
} |
ctx->is224 = is224; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, |
int is224 ) |
{ |
mbedtls_sha256_starts_ret( ctx, is224 ); |
} |
#endif |
#if !defined(MBEDTLS_SHA256_PROCESS_ALT) |
static const uint32_t K[] = |
{ |
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, |
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, |
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, |
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, |
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, |
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, |
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, |
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, |
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, |
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, |
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, |
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, |
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, |
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, |
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, |
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, |
}; |
#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) |
#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) |
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) |
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) |
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) |
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) |
#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) |
#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) |
#define R(t) \ |
( \ |
W[t] = S1(W[(t) - 2]) + W[(t) - 7] + \ |
S0(W[(t) - 15]) + W[(t) - 16] \ |
) |
#define P(a,b,c,d,e,f,g,h,x,K) \ |
do \ |
{ \ |
temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ |
temp2 = S2(a) + F0((a),(b),(c)); \ |
(d) += temp1; (h) = temp1 + temp2; \ |
} while( 0 ) |
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, |
const unsigned char data[64] ) |
{ |
uint32_t temp1, temp2, W[64]; |
uint32_t A[8]; |
unsigned int i; |
SHA256_VALIDATE_RET( ctx != NULL ); |
SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); |
for( i = 0; i < 8; i++ ) |
A[i] = ctx->state[i]; |
#if defined(MBEDTLS_SHA256_SMALLER) |
for( i = 0; i < 64; i++ ) |
{ |
if( i < 16 ) |
GET_UINT32_BE( W[i], data, 4 * i ); |
else |
R( i ); |
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); |
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; |
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; |
} |
#else /* MBEDTLS_SHA256_SMALLER */ |
for( i = 0; i < 16; i++ ) |
GET_UINT32_BE( W[i], data, 4 * i ); |
for( i = 0; i < 16; i += 8 ) |
{ |
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); |
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); |
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); |
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); |
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); |
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); |
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); |
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); |
} |
for( i = 16; i < 64; i += 8 ) |
{ |
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); |
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); |
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); |
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); |
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); |
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); |
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); |
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); |
} |
#endif /* MBEDTLS_SHA256_SMALLER */ |
for( i = 0; i < 8; i++ ) |
ctx->state[i] += A[i]; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, |
const unsigned char data[64] ) |
{ |
mbedtls_internal_sha256_process( ctx, data ); |
} |
#endif |
#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ |
/* |
* SHA-256 process buffer |
*/ |
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
int ret; |
size_t fill; |
uint32_t left; |
SHA256_VALIDATE_RET( ctx != NULL ); |
SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); |
if( ilen == 0 ) |
return( 0 ); |
left = ctx->total[0] & 0x3F; |
fill = 64 - left; |
ctx->total[0] += (uint32_t) ilen; |
ctx->total[0] &= 0xFFFFFFFF; |
if( ctx->total[0] < (uint32_t) ilen ) |
ctx->total[1]++; |
if( left && ilen >= fill ) |
{ |
memcpy( (void *) (ctx->buffer + left), input, fill ); |
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
input += fill; |
ilen -= fill; |
left = 0; |
} |
while( ilen >= 64 ) |
{ |
if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) |
return( ret ); |
input += 64; |
ilen -= 64; |
} |
if( ilen > 0 ) |
memcpy( (void *) (ctx->buffer + left), input, ilen ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
mbedtls_sha256_update_ret( ctx, input, ilen ); |
} |
#endif |
/* |
* SHA-256 final digest |
*/ |
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, |
unsigned char output[32] ) |
{ |
int ret; |
uint32_t used; |
uint32_t high, low; |
SHA256_VALIDATE_RET( ctx != NULL ); |
SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); |
/* |
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length |
*/ |
used = ctx->total[0] & 0x3F; |
ctx->buffer[used++] = 0x80; |
if( used <= 56 ) |
{ |
/* Enough room for padding + length in current block */ |
memset( ctx->buffer + used, 0, 56 - used ); |
} |
else |
{ |
/* We'll need an extra block */ |
memset( ctx->buffer + used, 0, 64 - used ); |
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
memset( ctx->buffer, 0, 56 ); |
} |
/* |
* Add message length |
*/ |
high = ( ctx->total[0] >> 29 ) |
| ( ctx->total[1] << 3 ); |
low = ( ctx->total[0] << 3 ); |
PUT_UINT32_BE( high, ctx->buffer, 56 ); |
PUT_UINT32_BE( low, ctx->buffer, 60 ); |
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
/* |
* Output final state |
*/ |
PUT_UINT32_BE( ctx->state[0], output, 0 ); |
PUT_UINT32_BE( ctx->state[1], output, 4 ); |
PUT_UINT32_BE( ctx->state[2], output, 8 ); |
PUT_UINT32_BE( ctx->state[3], output, 12 ); |
PUT_UINT32_BE( ctx->state[4], output, 16 ); |
PUT_UINT32_BE( ctx->state[5], output, 20 ); |
PUT_UINT32_BE( ctx->state[6], output, 24 ); |
if( ctx->is224 == 0 ) |
PUT_UINT32_BE( ctx->state[7], output, 28 ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, |
unsigned char output[32] ) |
{ |
mbedtls_sha256_finish_ret( ctx, output ); |
} |
#endif |
#endif /* !MBEDTLS_SHA256_ALT */ |
/* |
* output = SHA-256( input buffer ) |
*/ |
int mbedtls_sha256_ret( const unsigned char *input, |
size_t ilen, |
unsigned char output[32], |
int is224 ) |
{ |
int ret; |
mbedtls_sha256_context ctx; |
SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); |
SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); |
SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); |
mbedtls_sha256_init( &ctx ); |
if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_sha256_free( &ctx ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha256( const unsigned char *input, |
size_t ilen, |
unsigned char output[32], |
int is224 ) |
{ |
mbedtls_sha256_ret( input, ilen, output, is224 ); |
} |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* FIPS-180-2 test vectors |
*/ |
static const unsigned char sha256_test_buf[3][57] = |
{ |
{ "abc" }, |
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, |
{ "" } |
}; |
static const size_t sha256_test_buflen[3] = |
{ |
3, 56, 1000 |
}; |
static const unsigned char sha256_test_sum[6][32] = |
{ |
/* |
* SHA-224 test vectors |
*/ |
{ 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, |
0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, |
0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, |
0xE3, 0x6C, 0x9D, 0xA7 }, |
{ 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, |
0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, |
0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, |
0x52, 0x52, 0x25, 0x25 }, |
{ 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, |
0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, |
0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, |
0x4E, 0xE7, 0xAD, 0x67 }, |
/* |
* SHA-256 test vectors |
*/ |
{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, |
0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, |
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, |
0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, |
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, |
0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, |
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, |
0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, |
{ 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, |
0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, |
0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, |
0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_sha256_self_test( int verbose ) |
{ |
int i, j, k, buflen, ret = 0; |
unsigned char *buf; |
unsigned char sha256sum[32]; |
mbedtls_sha256_context ctx; |
buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); |
if( NULL == buf ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "Buffer allocation failed\n" ); |
return( 1 ); |
} |
mbedtls_sha256_init( &ctx ); |
for( i = 0; i < 6; i++ ) |
{ |
j = i % 3; |
k = i < 3; |
if( verbose != 0 ) |
mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); |
if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) |
goto fail; |
if( j == 2 ) |
{ |
memset( buf, 'a', buflen = 1000 ); |
for( j = 0; j < 1000; j++ ) |
{ |
ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); |
if( ret != 0 ) |
goto fail; |
} |
} |
else |
{ |
ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], |
sha256_test_buflen[j] ); |
if( ret != 0 ) |
goto fail; |
} |
if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) |
goto fail; |
if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) |
{ |
ret = 1; |
goto fail; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
goto exit; |
fail: |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
exit: |
mbedtls_sha256_free( &ctx ); |
mbedtls_free( buf ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_SHA256_C */ |
/programs/develop/libraries/kos_mbedtls/library/sha512.c |
---|
0,0 → 1,638 |
/* |
* FIPS-180-2 compliant SHA-384/512 implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The SHA-512 Secure Hash Standard was published by NIST in 2002. |
* |
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SHA512_C) |
#include "mbedtls/sha512.h" |
#include "mbedtls/platform_util.h" |
#if defined(_MSC_VER) || defined(__WATCOMC__) |
#define UL64(x) x##ui64 |
#else |
#define UL64(x) x##ULL |
#endif |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#include <stdlib.h> |
#define mbedtls_printf printf |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#define SHA512_VALIDATE_RET(cond) \ |
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) |
#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) |
#if !defined(MBEDTLS_SHA512_ALT) |
/* |
* 64-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT64_BE |
#define GET_UINT64_BE(n,b,i) \ |
{ \ |
(n) = ( (uint64_t) (b)[(i) ] << 56 ) \ |
| ( (uint64_t) (b)[(i) + 1] << 48 ) \ |
| ( (uint64_t) (b)[(i) + 2] << 40 ) \ |
| ( (uint64_t) (b)[(i) + 3] << 32 ) \ |
| ( (uint64_t) (b)[(i) + 4] << 24 ) \ |
| ( (uint64_t) (b)[(i) + 5] << 16 ) \ |
| ( (uint64_t) (b)[(i) + 6] << 8 ) \ |
| ( (uint64_t) (b)[(i) + 7] ); \ |
} |
#endif /* GET_UINT64_BE */ |
#ifndef PUT_UINT64_BE |
#define PUT_UINT64_BE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ |
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 7] = (unsigned char) ( (n) ); \ |
} |
#endif /* PUT_UINT64_BE */ |
void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) |
{ |
SHA512_VALIDATE( ctx != NULL ); |
memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); |
} |
void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); |
} |
void mbedtls_sha512_clone( mbedtls_sha512_context *dst, |
const mbedtls_sha512_context *src ) |
{ |
SHA512_VALIDATE( dst != NULL ); |
SHA512_VALIDATE( src != NULL ); |
*dst = *src; |
} |
/* |
* SHA-512 context setup |
*/ |
int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) |
{ |
SHA512_VALIDATE_RET( ctx != NULL ); |
SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); |
ctx->total[0] = 0; |
ctx->total[1] = 0; |
if( is384 == 0 ) |
{ |
/* SHA-512 */ |
ctx->state[0] = UL64(0x6A09E667F3BCC908); |
ctx->state[1] = UL64(0xBB67AE8584CAA73B); |
ctx->state[2] = UL64(0x3C6EF372FE94F82B); |
ctx->state[3] = UL64(0xA54FF53A5F1D36F1); |
ctx->state[4] = UL64(0x510E527FADE682D1); |
ctx->state[5] = UL64(0x9B05688C2B3E6C1F); |
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); |
ctx->state[7] = UL64(0x5BE0CD19137E2179); |
} |
else |
{ |
/* SHA-384 */ |
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); |
ctx->state[1] = UL64(0x629A292A367CD507); |
ctx->state[2] = UL64(0x9159015A3070DD17); |
ctx->state[3] = UL64(0x152FECD8F70E5939); |
ctx->state[4] = UL64(0x67332667FFC00B31); |
ctx->state[5] = UL64(0x8EB44A8768581511); |
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); |
ctx->state[7] = UL64(0x47B5481DBEFA4FA4); |
} |
ctx->is384 = is384; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, |
int is384 ) |
{ |
mbedtls_sha512_starts_ret( ctx, is384 ); |
} |
#endif |
#if !defined(MBEDTLS_SHA512_PROCESS_ALT) |
/* |
* Round constants |
*/ |
static const uint64_t K[80] = |
{ |
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), |
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), |
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), |
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), |
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), |
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), |
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), |
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), |
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), |
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), |
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), |
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), |
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), |
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), |
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), |
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), |
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), |
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), |
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), |
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), |
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), |
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), |
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), |
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), |
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), |
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), |
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), |
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), |
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), |
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), |
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), |
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), |
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), |
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), |
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), |
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), |
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), |
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), |
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), |
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) |
}; |
int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, |
const unsigned char data[128] ) |
{ |
int i; |
uint64_t temp1, temp2, W[80]; |
uint64_t A, B, C, D, E, F, G, H; |
SHA512_VALIDATE_RET( ctx != NULL ); |
SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); |
#define SHR(x,n) ((x) >> (n)) |
#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n)))) |
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) |
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) |
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) |
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) |
#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) |
#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) |
#define P(a,b,c,d,e,f,g,h,x,K) \ |
do \ |
{ \ |
temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ |
temp2 = S2(a) + F0((a),(b),(c)); \ |
(d) += temp1; (h) = temp1 + temp2; \ |
} while( 0 ) |
for( i = 0; i < 16; i++ ) |
{ |
GET_UINT64_BE( W[i], data, i << 3 ); |
} |
for( ; i < 80; i++ ) |
{ |
W[i] = S1(W[i - 2]) + W[i - 7] + |
S0(W[i - 15]) + W[i - 16]; |
} |
A = ctx->state[0]; |
B = ctx->state[1]; |
C = ctx->state[2]; |
D = ctx->state[3]; |
E = ctx->state[4]; |
F = ctx->state[5]; |
G = ctx->state[6]; |
H = ctx->state[7]; |
i = 0; |
do |
{ |
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; |
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; |
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; |
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; |
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; |
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; |
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; |
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; |
} |
while( i < 80 ); |
ctx->state[0] += A; |
ctx->state[1] += B; |
ctx->state[2] += C; |
ctx->state[3] += D; |
ctx->state[4] += E; |
ctx->state[5] += F; |
ctx->state[6] += G; |
ctx->state[7] += H; |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha512_process( mbedtls_sha512_context *ctx, |
const unsigned char data[128] ) |
{ |
mbedtls_internal_sha512_process( ctx, data ); |
} |
#endif |
#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ |
/* |
* SHA-512 process buffer |
*/ |
int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
int ret; |
size_t fill; |
unsigned int left; |
SHA512_VALIDATE_RET( ctx != NULL ); |
SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); |
if( ilen == 0 ) |
return( 0 ); |
left = (unsigned int) (ctx->total[0] & 0x7F); |
fill = 128 - left; |
ctx->total[0] += (uint64_t) ilen; |
if( ctx->total[0] < (uint64_t) ilen ) |
ctx->total[1]++; |
if( left && ilen >= fill ) |
{ |
memcpy( (void *) (ctx->buffer + left), input, fill ); |
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
input += fill; |
ilen -= fill; |
left = 0; |
} |
while( ilen >= 128 ) |
{ |
if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) |
return( ret ); |
input += 128; |
ilen -= 128; |
} |
if( ilen > 0 ) |
memcpy( (void *) (ctx->buffer + left), input, ilen ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, |
const unsigned char *input, |
size_t ilen ) |
{ |
mbedtls_sha512_update_ret( ctx, input, ilen ); |
} |
#endif |
/* |
* SHA-512 final digest |
*/ |
int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, |
unsigned char output[64] ) |
{ |
int ret; |
unsigned used; |
uint64_t high, low; |
SHA512_VALIDATE_RET( ctx != NULL ); |
SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); |
/* |
* Add padding: 0x80 then 0x00 until 16 bytes remain for the length |
*/ |
used = ctx->total[0] & 0x7F; |
ctx->buffer[used++] = 0x80; |
if( used <= 112 ) |
{ |
/* Enough room for padding + length in current block */ |
memset( ctx->buffer + used, 0, 112 - used ); |
} |
else |
{ |
/* We'll need an extra block */ |
memset( ctx->buffer + used, 0, 128 - used ); |
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
memset( ctx->buffer, 0, 112 ); |
} |
/* |
* Add message length |
*/ |
high = ( ctx->total[0] >> 61 ) |
| ( ctx->total[1] << 3 ); |
low = ( ctx->total[0] << 3 ); |
PUT_UINT64_BE( high, ctx->buffer, 112 ); |
PUT_UINT64_BE( low, ctx->buffer, 120 ); |
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) |
return( ret ); |
/* |
* Output final state |
*/ |
PUT_UINT64_BE( ctx->state[0], output, 0 ); |
PUT_UINT64_BE( ctx->state[1], output, 8 ); |
PUT_UINT64_BE( ctx->state[2], output, 16 ); |
PUT_UINT64_BE( ctx->state[3], output, 24 ); |
PUT_UINT64_BE( ctx->state[4], output, 32 ); |
PUT_UINT64_BE( ctx->state[5], output, 40 ); |
if( ctx->is384 == 0 ) |
{ |
PUT_UINT64_BE( ctx->state[6], output, 48 ); |
PUT_UINT64_BE( ctx->state[7], output, 56 ); |
} |
return( 0 ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, |
unsigned char output[64] ) |
{ |
mbedtls_sha512_finish_ret( ctx, output ); |
} |
#endif |
#endif /* !MBEDTLS_SHA512_ALT */ |
/* |
* output = SHA-512( input buffer ) |
*/ |
int mbedtls_sha512_ret( const unsigned char *input, |
size_t ilen, |
unsigned char output[64], |
int is384 ) |
{ |
int ret; |
mbedtls_sha512_context ctx; |
SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); |
SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); |
SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); |
mbedtls_sha512_init( &ctx ); |
if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) |
goto exit; |
exit: |
mbedtls_sha512_free( &ctx ); |
return( ret ); |
} |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
void mbedtls_sha512( const unsigned char *input, |
size_t ilen, |
unsigned char output[64], |
int is384 ) |
{ |
mbedtls_sha512_ret( input, ilen, output, is384 ); |
} |
#endif |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* FIPS-180-2 test vectors |
*/ |
static const unsigned char sha512_test_buf[3][113] = |
{ |
{ "abc" }, |
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" |
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, |
{ "" } |
}; |
static const size_t sha512_test_buflen[3] = |
{ |
3, 112, 1000 |
}; |
static const unsigned char sha512_test_sum[6][64] = |
{ |
/* |
* SHA-384 test vectors |
*/ |
{ 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, |
0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, |
0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, |
0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, |
0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, |
0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, |
{ 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, |
0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, |
0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, |
0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, |
0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, |
0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, |
{ 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, |
0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, |
0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, |
0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, |
0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, |
0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, |
/* |
* SHA-512 test vectors |
*/ |
{ 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, |
0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, |
0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, |
0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, |
0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, |
0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, |
0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, |
0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, |
{ 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, |
0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, |
0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, |
0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, |
0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, |
0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, |
0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, |
0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, |
{ 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, |
0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, |
0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, |
0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, |
0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, |
0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, |
0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, |
0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_sha512_self_test( int verbose ) |
{ |
int i, j, k, buflen, ret = 0; |
unsigned char *buf; |
unsigned char sha512sum[64]; |
mbedtls_sha512_context ctx; |
buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); |
if( NULL == buf ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "Buffer allocation failed\n" ); |
return( 1 ); |
} |
mbedtls_sha512_init( &ctx ); |
for( i = 0; i < 6; i++ ) |
{ |
j = i % 3; |
k = i < 3; |
if( verbose != 0 ) |
mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); |
if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) |
goto fail; |
if( j == 2 ) |
{ |
memset( buf, 'a', buflen = 1000 ); |
for( j = 0; j < 1000; j++ ) |
{ |
ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); |
if( ret != 0 ) |
goto fail; |
} |
} |
else |
{ |
ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], |
sha512_test_buflen[j] ); |
if( ret != 0 ) |
goto fail; |
} |
if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) |
goto fail; |
if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) |
{ |
ret = 1; |
goto fail; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
goto exit; |
fail: |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
exit: |
mbedtls_sha512_free( &ctx ); |
mbedtls_free( buf ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_SHA512_C */ |
/programs/develop/libraries/kos_mbedtls/library/ssl_cache.c |
---|
0,0 → 1,329 |
/* |
* SSL session cache implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* These session callbacks use a simple chained list |
* to store and retrieve the session information. |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SSL_CACHE_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/ssl_cache.h" |
#include <string.h> |
void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) |
{ |
memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); |
cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; |
cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &cache->mutex ); |
#endif |
} |
int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) |
{ |
int ret = 1; |
#if defined(MBEDTLS_HAVE_TIME) |
mbedtls_time_t t = mbedtls_time( NULL ); |
#endif |
mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; |
mbedtls_ssl_cache_entry *cur, *entry; |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) |
return( 1 ); |
#endif |
cur = cache->chain; |
entry = NULL; |
while( cur != NULL ) |
{ |
entry = cur; |
cur = cur->next; |
#if defined(MBEDTLS_HAVE_TIME) |
if( cache->timeout != 0 && |
(int) ( t - entry->timestamp ) > cache->timeout ) |
continue; |
#endif |
if( session->ciphersuite != entry->session.ciphersuite || |
session->compression != entry->session.compression || |
session->id_len != entry->session.id_len ) |
continue; |
if( memcmp( session->id, entry->session.id, |
entry->session.id_len ) != 0 ) |
continue; |
memcpy( session->master, entry->session.master, 48 ); |
session->verify_result = entry->session.verify_result; |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
/* |
* Restore peer certificate (without rest of the original chain) |
*/ |
if( entry->peer_cert.p != NULL ) |
{ |
if( ( session->peer_cert = mbedtls_calloc( 1, |
sizeof(mbedtls_x509_crt) ) ) == NULL ) |
{ |
ret = 1; |
goto exit; |
} |
mbedtls_x509_crt_init( session->peer_cert ); |
if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, |
entry->peer_cert.len ) != 0 ) |
{ |
mbedtls_free( session->peer_cert ); |
session->peer_cert = NULL; |
ret = 1; |
goto exit; |
} |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
ret = 0; |
goto exit; |
} |
exit: |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) |
ret = 1; |
#endif |
return( ret ); |
} |
int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) |
{ |
int ret = 1; |
#if defined(MBEDTLS_HAVE_TIME) |
mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; |
mbedtls_ssl_cache_entry *old = NULL; |
#endif |
mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; |
mbedtls_ssl_cache_entry *cur, *prv; |
int count = 0; |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) |
return( ret ); |
#endif |
cur = cache->chain; |
prv = NULL; |
while( cur != NULL ) |
{ |
count++; |
#if defined(MBEDTLS_HAVE_TIME) |
if( cache->timeout != 0 && |
(int) ( t - cur->timestamp ) > cache->timeout ) |
{ |
cur->timestamp = t; |
break; /* expired, reuse this slot, update timestamp */ |
} |
#endif |
if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) |
break; /* client reconnected, keep timestamp for session id */ |
#if defined(MBEDTLS_HAVE_TIME) |
if( oldest == 0 || cur->timestamp < oldest ) |
{ |
oldest = cur->timestamp; |
old = cur; |
} |
#endif |
prv = cur; |
cur = cur->next; |
} |
if( cur == NULL ) |
{ |
#if defined(MBEDTLS_HAVE_TIME) |
/* |
* Reuse oldest entry if max_entries reached |
*/ |
if( count >= cache->max_entries ) |
{ |
if( old == NULL ) |
{ |
ret = 1; |
goto exit; |
} |
cur = old; |
} |
#else /* MBEDTLS_HAVE_TIME */ |
/* |
* Reuse first entry in chain if max_entries reached, |
* but move to last place |
*/ |
if( count >= cache->max_entries ) |
{ |
if( cache->chain == NULL ) |
{ |
ret = 1; |
goto exit; |
} |
cur = cache->chain; |
cache->chain = cur->next; |
cur->next = NULL; |
prv->next = cur; |
} |
#endif /* MBEDTLS_HAVE_TIME */ |
else |
{ |
/* |
* max_entries not reached, create new entry |
*/ |
cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); |
if( cur == NULL ) |
{ |
ret = 1; |
goto exit; |
} |
if( prv == NULL ) |
cache->chain = cur; |
else |
prv->next = cur; |
} |
#if defined(MBEDTLS_HAVE_TIME) |
cur->timestamp = t; |
#endif |
} |
memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) ); |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
/* |
* If we're reusing an entry, free its certificate first |
*/ |
if( cur->peer_cert.p != NULL ) |
{ |
mbedtls_free( cur->peer_cert.p ); |
memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); |
} |
/* |
* Store peer certificate |
*/ |
if( session->peer_cert != NULL ) |
{ |
cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len ); |
if( cur->peer_cert.p == NULL ) |
{ |
ret = 1; |
goto exit; |
} |
memcpy( cur->peer_cert.p, session->peer_cert->raw.p, |
session->peer_cert->raw.len ); |
cur->peer_cert.len = session->peer_cert->raw.len; |
cur->session.peer_cert = NULL; |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
ret = 0; |
exit: |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) |
ret = 1; |
#endif |
return( ret ); |
} |
#if defined(MBEDTLS_HAVE_TIME) |
void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) |
{ |
if( timeout < 0 ) timeout = 0; |
cache->timeout = timeout; |
} |
#endif /* MBEDTLS_HAVE_TIME */ |
void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) |
{ |
if( max < 0 ) max = 0; |
cache->max_entries = max; |
} |
void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) |
{ |
mbedtls_ssl_cache_entry *cur, *prv; |
cur = cache->chain; |
while( cur != NULL ) |
{ |
prv = cur; |
cur = cur->next; |
mbedtls_ssl_session_free( &prv->session ); |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
mbedtls_free( prv->peer_cert.p ); |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
mbedtls_free( prv ); |
} |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &cache->mutex ); |
#endif |
cache->chain = NULL; |
} |
#endif /* MBEDTLS_SSL_CACHE_C */ |
/programs/develop/libraries/kos_mbedtls/library/ssl_ciphersuites.c |
---|
0,0 → 1,2375 |
/** |
* \file ssl_ciphersuites.c |
* |
* \brief SSL ciphersuites for mbed TLS |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SSL_TLS_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#endif |
#include "mbedtls/ssl_ciphersuites.h" |
#include "mbedtls/ssl.h" |
#include <string.h> |
/* |
* Ordered from most preferred to least preferred in terms of security. |
* |
* Current rule (except RC4 and 3DES, weak and null which come last): |
* 1. By key exchange: |
* Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK |
* 2. By key length and cipher: |
* ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 |
* 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 |
* 4. By hash function used when relevant |
* 5. By key exchange/auth again: EC > non-EC |
*/ |
static const int ciphersuite_preference[] = |
{ |
#if defined(MBEDTLS_SSL_CIPHERSUITES) |
MBEDTLS_SSL_CIPHERSUITES, |
#else |
/* Chacha-Poly ephemeral suites */ |
MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, |
/* All AES-256 ephemeral suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, |
/* All CAMELLIA-256 ephemeral suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, |
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, |
/* All ARIA-256 ephemeral suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, |
/* All AES-128 ephemeral suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, |
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, |
/* All CAMELLIA-128 ephemeral suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, |
/* All ARIA-128 ephemeral suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, |
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, |
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, |
/* The PSK ephemeral suites */ |
MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, |
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, |
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, |
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, |
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, |
/* The ECJPAKE suite */ |
MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, |
/* All AES-256 suites */ |
MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_RSA_WITH_AES_256_CCM, |
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, |
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, |
/* All CAMELLIA-256 suites */ |
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, |
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, |
MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, |
/* All ARIA-256 suites */ |
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, |
/* All AES-128 suites */ |
MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_RSA_WITH_AES_128_CCM, |
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, |
/* All CAMELLIA-128 suites */ |
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, |
MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, |
/* All ARIA-128 suites */ |
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, |
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, |
MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, |
/* The RSA PSK suites */ |
MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, |
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, |
/* The PSK suites */ |
MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, |
MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, |
MBEDTLS_TLS_PSK_WITH_AES_256_CCM, |
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, |
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, |
MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, |
MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, |
MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, |
MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, |
MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_PSK_WITH_AES_128_CCM, |
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, |
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, |
MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, |
MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, |
MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, |
MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, |
/* 3DES suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, |
MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, |
/* RC4 suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, |
MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, |
MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, |
MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, |
MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, |
MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, |
MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, |
MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, |
MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, |
/* Weak suites */ |
MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, |
MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, |
/* NULL suites */ |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, |
MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, |
MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, |
MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, |
MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, |
MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, |
MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, |
MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, |
MBEDTLS_TLS_RSA_WITH_NULL_SHA256, |
MBEDTLS_TLS_RSA_WITH_NULL_SHA, |
MBEDTLS_TLS_RSA_WITH_NULL_MD5, |
MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, |
MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, |
MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, |
MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, |
MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, |
MBEDTLS_TLS_PSK_WITH_NULL_SHA384, |
MBEDTLS_TLS_PSK_WITH_NULL_SHA256, |
MBEDTLS_TLS_PSK_WITH_NULL_SHA, |
#endif /* MBEDTLS_SSL_CIPHERSUITES */ |
0 |
}; |
static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = |
{ |
#if defined(MBEDTLS_CHACHAPOLY_C) && \ |
defined(MBEDTLS_SHA256_C) && \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, |
"TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", |
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, |
MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, |
"TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", |
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, |
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) |
{ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, |
"TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", |
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, |
MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
{ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, |
"TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", |
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, |
MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, |
"TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", |
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, |
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
{ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, |
"TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", |
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, |
MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
{ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, |
"TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", |
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, |
MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_CHACHAPOLY_C && |
MBEDTLS_SHA256_C && |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_SHA1_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_SHA1_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_SHA256_C) |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_SHA256_C) |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA1_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
{ MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_MD5_C) |
{ MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif |
#endif /* MBEDTLS_ARC4_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_SHA1_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_SHA1_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
{ MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", |
MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", |
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", |
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", |
MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
{ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", |
MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_GCM_C) |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_GCM_C */ |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", |
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_ARC4_C) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", |
MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_NODTLS }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_ARC4_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
#if defined(MBEDTLS_AES_C) |
#if defined(MBEDTLS_CCM_C) |
{ MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", |
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_SHORT_TAG }, |
#endif /* MBEDTLS_CCM_C */ |
#endif /* MBEDTLS_AES_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
#if defined(MBEDTLS_MD5_C) |
{ MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#if defined(MBEDTLS_SHA512_C) |
{ MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", |
MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ |
#if defined(MBEDTLS_DES_C) |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", |
MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
#if defined(MBEDTLS_SHA1_C) |
{ MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", |
MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_CIPHERSUITE_WEAK }, |
#endif /* MBEDTLS_SHA1_C */ |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* MBEDTLS_DES_C */ |
#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ |
#if defined(MBEDTLS_ARIA_C) |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, |
"TLS-RSA-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, |
"TLS-RSA-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, |
"TLS-RSA-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, |
"TLS-RSA-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, |
"TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, |
"TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, |
"TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, |
"TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, |
"TLS-PSK-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, |
"TLS-PSK-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, |
"TLS-PSK-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, |
"TLS-PSK-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, |
"TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, |
"TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, |
"TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, |
"TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, |
"TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, |
"TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, |
"TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, |
"TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, |
"TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, |
"TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, |
"TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, |
"TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, |
"TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, |
"TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, |
"TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, |
"TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, |
"TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, |
"TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, |
"TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, |
"TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, |
"TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, |
"TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, |
"TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", |
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) |
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, |
"TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", |
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, |
"TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", |
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) |
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, |
"TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", |
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, |
0 }, |
#endif |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#endif /* MBEDTLS_ARIA_C */ |
{ 0, "", |
MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, |
0, 0, 0, 0, 0 } |
}; |
#if defined(MBEDTLS_SSL_CIPHERSUITES) |
const int *mbedtls_ssl_list_ciphersuites( void ) |
{ |
return( ciphersuite_preference ); |
} |
#else |
#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ |
sizeof( ciphersuite_definitions[0] ) |
static int supported_ciphersuites[MAX_CIPHERSUITES]; |
static int supported_init = 0; |
static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) |
{ |
(void)cs_info; |
#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) |
if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) |
return( 1 ); |
#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ |
#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) |
if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB || |
cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC ) |
{ |
return( 1 ); |
} |
#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ |
return( 0 ); |
} |
const int *mbedtls_ssl_list_ciphersuites( void ) |
{ |
/* |
* On initial call filter out all ciphersuites not supported by current |
* build based on presence in the ciphersuite_definitions. |
*/ |
if( supported_init == 0 ) |
{ |
const int *p; |
int *q; |
for( p = ciphersuite_preference, q = supported_ciphersuites; |
*p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; |
p++ ) |
{ |
const mbedtls_ssl_ciphersuite_t *cs_info; |
if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && |
!ciphersuite_is_removed( cs_info ) ) |
{ |
*(q++) = *p; |
} |
} |
*q = 0; |
supported_init = 1; |
} |
return( supported_ciphersuites ); |
} |
#endif /* MBEDTLS_SSL_CIPHERSUITES */ |
const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( |
const char *ciphersuite_name ) |
{ |
const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; |
if( NULL == ciphersuite_name ) |
return( NULL ); |
while( cur->id != 0 ) |
{ |
if( 0 == strcmp( cur->name, ciphersuite_name ) ) |
return( cur ); |
cur++; |
} |
return( NULL ); |
} |
const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) |
{ |
const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; |
while( cur->id != 0 ) |
{ |
if( cur->id == ciphersuite ) |
return( cur ); |
cur++; |
} |
return( NULL ); |
} |
const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) |
{ |
const mbedtls_ssl_ciphersuite_t *cur; |
cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); |
if( cur == NULL ) |
return( "unknown" ); |
return( cur->name ); |
} |
int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) |
{ |
const mbedtls_ssl_ciphersuite_t *cur; |
cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); |
if( cur == NULL ) |
return( 0 ); |
return( cur->id ); |
} |
#if defined(MBEDTLS_PK_C) |
mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) |
{ |
switch( info->key_exchange ) |
{ |
case MBEDTLS_KEY_EXCHANGE_RSA: |
case MBEDTLS_KEY_EXCHANGE_DHE_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: |
case MBEDTLS_KEY_EXCHANGE_RSA_PSK: |
return( MBEDTLS_PK_RSA ); |
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: |
return( MBEDTLS_PK_ECDSA ); |
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: |
return( MBEDTLS_PK_ECKEY ); |
default: |
return( MBEDTLS_PK_NONE ); |
} |
} |
mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) |
{ |
switch( info->key_exchange ) |
{ |
case MBEDTLS_KEY_EXCHANGE_RSA: |
case MBEDTLS_KEY_EXCHANGE_DHE_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: |
return( MBEDTLS_PK_RSA ); |
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: |
return( MBEDTLS_PK_ECDSA ); |
default: |
return( MBEDTLS_PK_NONE ); |
} |
} |
#endif /* MBEDTLS_PK_C */ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) |
{ |
switch( info->key_exchange ) |
{ |
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: |
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: |
case MBEDTLS_KEY_EXCHANGE_ECJPAKE: |
return( 1 ); |
default: |
return( 0 ); |
} |
} |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) |
{ |
switch( info->key_exchange ) |
{ |
case MBEDTLS_KEY_EXCHANGE_PSK: |
case MBEDTLS_KEY_EXCHANGE_RSA_PSK: |
case MBEDTLS_KEY_EXCHANGE_DHE_PSK: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: |
return( 1 ); |
default: |
return( 0 ); |
} |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ |
#endif /* MBEDTLS_SSL_TLS_C */ |
/programs/develop/libraries/kos_mbedtls/library/ssl_cli.c |
---|
0,0 → 1,3650 |
/* |
* SSLv3/TLSv1 client-side functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SSL_CLI_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/debug.h" |
#include "mbedtls/ssl.h" |
#include "mbedtls/ssl_internal.h" |
#include <string.h> |
#include <stdint.h> |
#if defined(MBEDTLS_HAVE_TIME) |
#include "mbedtls/platform_time.h" |
#endif |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
#include "mbedtls/platform_util.h" |
#endif |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
size_t hostname_len; |
*olen = 0; |
if( ssl->hostname == NULL ) |
return; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", |
ssl->hostname ) ); |
hostname_len = strlen( ssl->hostname ); |
if( end < p || (size_t)( end - p ) < hostname_len + 9 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
/* |
* Sect. 3, RFC 6066 (TLS Extensions Definitions) |
* |
* In order to provide any of the server names, clients MAY include an |
* extension of type "server_name" in the (extended) client hello. The |
* "extension_data" field of this extension SHALL contain |
* "ServerNameList" where: |
* |
* struct { |
* NameType name_type; |
* select (name_type) { |
* case host_name: HostName; |
* } name; |
* } ServerName; |
* |
* enum { |
* host_name(0), (255) |
* } NameType; |
* |
* opaque HostName<1..2^16-1>; |
* |
* struct { |
* ServerName server_name_list<1..2^16-1> |
* } ServerNameList; |
* |
*/ |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); |
*p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); |
*p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); |
*p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( hostname_len ) & 0xFF ); |
memcpy( p, ssl->hostname, hostname_len ); |
*olen = hostname_len + 9; |
} |
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
*olen = 0; |
/* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the |
* initial ClientHello, in which case also adding the renegotiation |
* info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ |
if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
return; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); |
if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
/* |
* Secure renegotiation |
*/ |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); |
*p++ = 0x00; |
*p++ = ( ssl->verify_data_len + 1 ) & 0xFF; |
*p++ = ssl->verify_data_len & 0xFF; |
memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); |
*olen = 5 + ssl->verify_data_len; |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
/* |
* Only if we handle at least one key exchange that needs signatures. |
*/ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
size_t sig_alg_len = 0; |
const int *md; |
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) |
unsigned char *sig_alg_list = buf + 6; |
#endif |
*olen = 0; |
if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) |
return; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); |
for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) |
{ |
#if defined(MBEDTLS_ECDSA_C) |
sig_alg_len += 2; |
#endif |
#if defined(MBEDTLS_RSA_C) |
sig_alg_len += 2; |
#endif |
} |
if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
/* |
* Prepare signature_algorithms extension (TLS 1.2) |
*/ |
sig_alg_len = 0; |
for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) |
{ |
#if defined(MBEDTLS_ECDSA_C) |
sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); |
sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; |
#endif |
#if defined(MBEDTLS_RSA_C) |
sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); |
sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; |
#endif |
} |
/* |
* enum { |
* none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), |
* sha512(6), (255) |
* } HashAlgorithm; |
* |
* enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } |
* SignatureAlgorithm; |
* |
* struct { |
* HashAlgorithm hash; |
* SignatureAlgorithm signature; |
* } SignatureAndHashAlgorithm; |
* |
* SignatureAndHashAlgorithm |
* supported_signature_algorithms<2..2^16-2>; |
*/ |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); |
*p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); |
*p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); |
*olen = 6 + sig_alg_len; |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && |
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
unsigned char *elliptic_curve_list = p + 6; |
size_t elliptic_curve_len = 0; |
const mbedtls_ecp_curve_info *info; |
#if defined(MBEDTLS_ECP_C) |
const mbedtls_ecp_group_id *grp_id; |
#else |
((void) ssl); |
#endif |
*olen = 0; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); |
#if defined(MBEDTLS_ECP_C) |
for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) |
#else |
for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) |
#endif |
{ |
#if defined(MBEDTLS_ECP_C) |
info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); |
#endif |
if( info == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) ); |
return; |
} |
elliptic_curve_len += 2; |
} |
if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
elliptic_curve_len = 0; |
#if defined(MBEDTLS_ECP_C) |
for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) |
#else |
for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) |
#endif |
{ |
#if defined(MBEDTLS_ECP_C) |
info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); |
#endif |
elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; |
elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; |
} |
if( elliptic_curve_len == 0 ) |
return; |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); |
*p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); |
*p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); |
*olen = 6 + elliptic_curve_len; |
} |
static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
*olen = 0; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); |
if( end < p || (size_t)( end - p ) < 6 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 2; |
*p++ = 1; |
*p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; |
*olen = 6; |
} |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || |
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
int ret; |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
size_t kkpp_len; |
*olen = 0; |
/* Skip costly extension if we can't use EC J-PAKE anyway */ |
if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) |
return; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) ); |
if( end - p < 4 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); |
/* |
* We may need to send ClientHello multiple times for Hello verification. |
* We don't want to compute fresh values every time (both for performance |
* and consistency reasons), so cache the extension content. |
*/ |
if( ssl->handshake->ecjpake_cache == NULL || |
ssl->handshake->ecjpake_cache_len == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); |
ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, |
p + 2, end - p - 2, &kkpp_len, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); |
return; |
} |
ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); |
if( ssl->handshake->ecjpake_cache == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); |
return; |
} |
memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); |
ssl->handshake->ecjpake_cache_len = kkpp_len; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); |
kkpp_len = ssl->handshake->ecjpake_cache_len; |
if( (size_t)( end - p - 2 ) < kkpp_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); |
} |
*p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); |
*olen = kkpp_len + 4; |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
*olen = 0; |
if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) { |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); |
if( end < p || (size_t)( end - p ) < 5 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 1; |
*p++ = ssl->conf->mfl_code; |
*olen = 5; |
} |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
*olen = 0; |
if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) |
{ |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); |
if( end < p || (size_t)( end - p ) < 4 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 0x00; |
*olen = 4; |
} |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
*olen = 0; |
if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || |
ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " |
"extension" ) ); |
if( end < p || (size_t)( end - p ) < 4 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 0x00; |
*olen = 4; |
} |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
*olen = 0; |
if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || |
ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " |
"extension" ) ); |
if( end < p || (size_t)( end - p ) < 4 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 0x00; |
*olen = 4; |
} |
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
size_t tlen = ssl->session_negotiate->ticket_len; |
*olen = 0; |
if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) |
{ |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); |
if( end < p || (size_t)( end - p ) < 4 + tlen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); |
*p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( tlen ) & 0xFF ); |
*olen = 4; |
if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) |
{ |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); |
memcpy( p, ssl->session_negotiate->ticket, tlen ); |
*olen += tlen; |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
#if defined(MBEDTLS_SSL_ALPN) |
static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, size_t *olen ) |
{ |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
size_t alpnlen = 0; |
const char **cur; |
*olen = 0; |
if( ssl->conf->alpn_list == NULL ) |
{ |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); |
for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) |
alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1; |
if( end < p || (size_t)( end - p ) < 6 + alpnlen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); |
/* |
* opaque ProtocolName<1..2^8-1>; |
* |
* struct { |
* ProtocolName protocol_name_list<2..2^16-1> |
* } ProtocolNameList; |
*/ |
/* Skip writing extension and list length for now */ |
p += 4; |
for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) |
{ |
*p = (unsigned char)( strlen( *cur ) & 0xFF ); |
memcpy( p + 1, *cur, *p ); |
p += 1 + *p; |
} |
*olen = p - buf; |
/* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ |
buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); |
buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); |
/* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ |
buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); |
buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); |
} |
#endif /* MBEDTLS_SSL_ALPN */ |
/* |
* Generate random bytes for ClientHello |
*/ |
static int ssl_generate_random( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
unsigned char *p = ssl->handshake->randbytes; |
#if defined(MBEDTLS_HAVE_TIME) |
mbedtls_time_t t; |
#endif |
/* |
* When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake->verify_cookie != NULL ) |
{ |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_HAVE_TIME) |
t = mbedtls_time( NULL ); |
*p++ = (unsigned char)( t >> 24 ); |
*p++ = (unsigned char)( t >> 16 ); |
*p++ = (unsigned char)( t >> 8 ); |
*p++ = (unsigned char)( t ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); |
#else |
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) |
return( ret ); |
p += 4; |
#endif /* MBEDTLS_HAVE_TIME */ |
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
/** |
* \brief Validate cipher suite against config in SSL context. |
* |
* \param suite_info cipher suite to validate |
* \param ssl SSL context |
* \param min_minor_ver Minimal minor version to accept a cipher suite |
* \param max_minor_ver Maximal minor version to accept a cipher suite |
* |
* \return 0 if valid, else 1 |
*/ |
static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info, |
const mbedtls_ssl_context * ssl, |
int min_minor_ver, int max_minor_ver ) |
{ |
(void) ssl; |
if( suite_info == NULL ) |
return( 1 ); |
if( suite_info->min_minor_ver > max_minor_ver || |
suite_info->max_minor_ver < min_minor_ver ) |
return( 1 ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) |
return( 1 ); |
#endif |
#if defined(MBEDTLS_ARC4_C) |
if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && |
suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) |
return( 1 ); |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && |
mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) |
return( 1 ); |
#endif |
return( 0 ); |
} |
static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
size_t i, n, olen, ext_len = 0; |
unsigned char *buf; |
unsigned char *p, *q; |
unsigned char offer_compress; |
const int *ciphersuites; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info; |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
int uses_ec = 0; |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); |
if( ssl->conf->f_rng == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); |
return( MBEDTLS_ERR_SSL_NO_RNG ); |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
#endif |
{ |
ssl->major_ver = ssl->conf->min_major_ver; |
ssl->minor_ver = ssl->conf->min_minor_ver; |
} |
if( ssl->conf->max_major_ver == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, " |
"consider using mbedtls_ssl_config_defaults()" ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
/* |
* 0 . 0 handshake type |
* 1 . 3 handshake length |
* 4 . 5 highest version supported |
* 6 . 9 current UNIX time |
* 10 . 37 random bytes |
*/ |
buf = ssl->out_msg; |
p = buf + 4; |
mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, |
ssl->conf->transport, p ); |
p += 2; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", |
buf[4], buf[5] ) ); |
if( ( ret = ssl_generate_random( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); |
return( ret ); |
} |
memcpy( p, ssl->handshake->randbytes, 32 ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); |
p += 32; |
/* |
* 38 . 38 session id length |
* 39 . 39+n session id |
* 39+n . 39+n DTLS only: cookie length (1 byte) |
* 40+n . .. DTSL only: cookie |
* .. . .. ciphersuitelist length (2 bytes) |
* .. . .. ciphersuitelist |
* .. . .. compression methods length (1 byte) |
* .. . .. compression methods |
* .. . .. extensions length (2 bytes) |
* .. . .. extensions |
*/ |
n = ssl->session_negotiate->id_len; |
if( n < 16 || n > 32 || |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || |
#endif |
ssl->handshake->resume == 0 ) |
{ |
n = 0; |
} |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
/* |
* RFC 5077 section 3.4: "When presenting a ticket, the client MAY |
* generate and include a Session ID in the TLS ClientHello." |
*/ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
#endif |
{ |
if( ssl->session_negotiate->ticket != NULL && |
ssl->session_negotiate->ticket_len != 0 ) |
{ |
ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 ); |
if( ret != 0 ) |
return( ret ); |
ssl->session_negotiate->id_len = n = 32; |
} |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
*p++ = (unsigned char) n; |
for( i = 0; i < n; i++ ) |
*p++ = ssl->session_negotiate->id[i]; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); |
/* |
* DTLS cookie |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
if( ssl->handshake->verify_cookie == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); |
*p++ = 0; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", |
ssl->handshake->verify_cookie, |
ssl->handshake->verify_cookie_len ); |
*p++ = ssl->handshake->verify_cookie_len; |
memcpy( p, ssl->handshake->verify_cookie, |
ssl->handshake->verify_cookie_len ); |
p += ssl->handshake->verify_cookie_len; |
} |
} |
#endif |
/* |
* Ciphersuite list |
*/ |
ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; |
/* Skip writing ciphersuite length for now */ |
n = 0; |
q = p; |
p += 2; |
for( i = 0; ciphersuites[i] != 0; i++ ) |
{ |
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); |
if( ssl_validate_ciphersuite( ciphersuite_info, ssl, |
ssl->conf->min_minor_ver, |
ssl->conf->max_minor_ver ) != 0 ) |
continue; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", |
ciphersuites[i] ) ); |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); |
#endif |
n++; |
*p++ = (unsigned char)( ciphersuites[i] >> 8 ); |
*p++ = (unsigned char)( ciphersuites[i] ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); |
/* |
* Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV |
*/ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
#endif |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); |
*p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); |
*p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); |
n++; |
} |
/* Some versions of OpenSSL don't handle it correctly if not at end */ |
#if defined(MBEDTLS_SSL_FALLBACK_SCSV) |
if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); |
*p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); |
*p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); |
n++; |
} |
#endif |
*q++ = (unsigned char)( n >> 7 ); |
*q++ = (unsigned char)( n << 1 ); |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
offer_compress = 1; |
#else |
offer_compress = 0; |
#endif |
/* |
* We don't support compression with DTLS right now: if many records come |
* in the same datagram, uncompressing one could overwrite the next one. |
* We don't want to add complexity for handling that case unless there is |
* an actual need for it. |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
offer_compress = 0; |
#endif |
if( offer_compress ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", |
MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) ); |
*p++ = 2; |
*p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; |
*p++ = MBEDTLS_SSL_COMPRESS_NULL; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", |
MBEDTLS_SSL_COMPRESS_NULL ) ); |
*p++ = 1; |
*p++ = MBEDTLS_SSL_COMPRESS_NULL; |
} |
// First write extensions, then the total length |
// |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
/* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added |
* even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if( uses_ec ) |
{ |
ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
} |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_ALPN) |
ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
/* olen unused if all extensions are disabled */ |
((void) olen); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", |
ext_len ) ); |
if( ext_len > 0 ) |
{ |
*p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( ext_len ) & 0xFF ); |
p += ext_len; |
} |
ssl->out_msglen = p - buf; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; |
ssl->state++; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
mbedtls_ssl_send_flight_completed( ssl ); |
#endif |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); |
return( 0 ); |
} |
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
{ |
/* Check verify-data in constant-time. The length OTOH is no secret */ |
if( len != 1 + ssl->verify_data_len * 2 || |
buf[0] != ssl->verify_data_len * 2 || |
mbedtls_ssl_safer_memcmp( buf + 1, |
ssl->own_verify_data, ssl->verify_data_len ) != 0 || |
mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, |
ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
{ |
if( len != 1 || buf[0] != 0x00 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; |
} |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
/* |
* server should use the extension only if we did, |
* and if so the server's value should match ours (and len is always 1) |
*/ |
if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || |
len != 1 || |
buf[0] != ssl->conf->mfl_code ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || |
len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
((void) buf); |
ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || |
len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
((void) buf); |
ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || |
len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
((void) buf); |
ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || |
len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
((void) buf); |
ssl->handshake->new_session_ticket = 1; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
size_t list_size; |
const unsigned char *p; |
if( len == 0 || (size_t)( buf[0] + 1 ) != len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
list_size = buf[0]; |
p = buf + 1; |
while( list_size > 0 ) |
{ |
if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || |
p[0] == MBEDTLS_ECP_PF_COMPRESSED ) |
{ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) |
ssl->handshake->ecdh_ctx.point_format = p[0]; |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
ssl->handshake->ecjpake_ctx.point_format = p[0]; |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); |
return( 0 ); |
} |
list_size--; |
p++; |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || |
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
int ret; |
if( ssl->transform_negotiate->ciphersuite_info->key_exchange != |
MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); |
return( 0 ); |
} |
/* If we got here, we no longer need our cached extension */ |
mbedtls_free( ssl->handshake->ecjpake_cache ); |
ssl->handshake->ecjpake_cache = NULL; |
ssl->handshake->ecjpake_cache_len = 0; |
if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, |
buf, len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_SSL_ALPN) |
static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
size_t list_len, name_len; |
const char **p; |
/* If we didn't send it, the server shouldn't send it */ |
if( ssl->conf->alpn_list == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
/* |
* opaque ProtocolName<1..2^8-1>; |
* |
* struct { |
* ProtocolName protocol_name_list<2..2^16-1> |
* } ProtocolNameList; |
* |
* the "ProtocolNameList" MUST contain exactly one "ProtocolName" |
*/ |
/* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ |
if( len < 4 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
list_len = ( buf[0] << 8 ) | buf[1]; |
if( list_len != len - 2 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
name_len = buf[2]; |
if( name_len != list_len - 1 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
/* Check that the server chosen protocol was in our list and save it */ |
for( p = ssl->conf->alpn_list; *p != NULL; p++ ) |
{ |
if( name_len == strlen( *p ) && |
memcmp( buf + 3, *p, name_len ) == 0 ) |
{ |
ssl->alpn_chosen = *p; |
return( 0 ); |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
#endif /* MBEDTLS_SSL_ALPN */ |
/* |
* Parse HelloVerifyRequest. Only called after verifying the HS type. |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) |
{ |
const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); |
int major_ver, minor_ver; |
unsigned char cookie_len; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); |
/* Check that there is enough room for: |
* - 2 bytes of version |
* - 1 byte of cookie_len |
*/ |
if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, |
( "incoming HelloVerifyRequest message is too short" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
/* |
* struct { |
* ProtocolVersion server_version; |
* opaque cookie<0..2^8-1>; |
* } HelloVerifyRequest; |
*/ |
MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); |
mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); |
p += 2; |
/* |
* Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) |
* even is lower than our min version. |
*/ |
if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || |
minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || |
major_ver > ssl->conf->max_major_ver || |
minor_ver > ssl->conf->max_minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); |
return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); |
} |
cookie_len = *p++; |
if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, |
( "cookie length does not match incoming message size" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); |
mbedtls_free( ssl->handshake->verify_cookie ); |
ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); |
if( ssl->handshake->verify_cookie == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
memcpy( ssl->handshake->verify_cookie, p, cookie_len ); |
ssl->handshake->verify_cookie_len = cookie_len; |
/* Start over at ClientHello */ |
ssl->state = MBEDTLS_SSL_CLIENT_HELLO; |
mbedtls_ssl_reset_checksum( ssl ); |
mbedtls_ssl_recv_flight_completed( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) |
{ |
int ret, i; |
size_t n; |
size_t ext_len; |
unsigned char *buf, *ext; |
unsigned char comp; |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
int accept_comp; |
#endif |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
int renegotiation_info_seen = 0; |
#endif |
int handshake_failure = 0; |
const mbedtls_ssl_ciphersuite_t *suite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); |
buf = ssl->in_msg; |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
/* No alert on a read error. */ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
{ |
ssl->renego_records_seen++; |
if( ssl->conf->renego_max_records >= 0 && |
ssl->renego_records_seen > ssl->conf->renego_max_records ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " |
"but not honored by server" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); |
ssl->keep_current_message = 1; |
return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); |
return( ssl_parse_hello_verify_request( ssl ) ); |
} |
else |
{ |
/* We made it through the verification process */ |
mbedtls_free( ssl->handshake->verify_cookie ); |
ssl->handshake->verify_cookie = NULL; |
ssl->handshake->verify_cookie_len = 0; |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || |
buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
/* |
* 0 . 1 server_version |
* 2 . 33 random (maybe including 4 bytes of Unix time) |
* 34 . 34 session_id length = n |
* 35 . 34+n session_id |
* 35+n . 36+n cipher_suite |
* 37+n . 37+n compression_method |
* |
* 38+n . 39+n extensions length (optional) |
* 40+n . .. extensions |
*/ |
buf += mbedtls_ssl_hs_hdr_len( ssl ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); |
mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, |
ssl->conf->transport, buf + 0 ); |
if( ssl->major_ver < ssl->conf->min_major_ver || |
ssl->minor_ver < ssl->conf->min_minor_ver || |
ssl->major_ver > ssl->conf->max_major_ver || |
ssl->minor_ver > ssl->conf->max_minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - " |
" min: [%d:%d], server: [%d:%d], max: [%d:%d]", |
ssl->conf->min_major_ver, ssl->conf->min_minor_ver, |
ssl->major_ver, ssl->minor_ver, |
ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); |
return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", |
( (uint32_t) buf[2] << 24 ) | |
( (uint32_t) buf[3] << 16 ) | |
( (uint32_t) buf[4] << 8 ) | |
( (uint32_t) buf[5] ) ) ); |
memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); |
n = buf[34]; |
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); |
if( n > 32 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) |
{ |
ext_len = ( ( buf[38 + n] << 8 ) |
| ( buf[39 + n] ) ); |
if( ( ext_len > 0 && ext_len < 4 ) || |
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
} |
else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) |
{ |
ext_len = 0; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
/* ciphersuite (used later) */ |
i = ( buf[35 + n] << 8 ) | buf[36 + n]; |
/* |
* Read and check compression |
*/ |
comp = buf[37 + n]; |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
/* See comments in ssl_write_client_hello() */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
accept_comp = 0; |
else |
#endif |
accept_comp = 1; |
if( comp != MBEDTLS_SSL_COMPRESS_NULL && |
( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) |
#else /* MBEDTLS_ZLIB_SUPPORT */ |
if( comp != MBEDTLS_SSL_COMPRESS_NULL ) |
#endif/* MBEDTLS_ZLIB_SUPPORT */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); |
} |
/* |
* Initialize update checksum functions |
*/ |
ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); |
if( ssl->transform_negotiate->ciphersuite_info == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); |
/* |
* Check if the session can be resumed |
*/ |
if( ssl->handshake->resume == 0 || n == 0 || |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || |
#endif |
ssl->session_negotiate->ciphersuite != i || |
ssl->session_negotiate->compression != comp || |
ssl->session_negotiate->id_len != n || |
memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) |
{ |
ssl->state++; |
ssl->handshake->resume = 0; |
#if defined(MBEDTLS_HAVE_TIME) |
ssl->session_negotiate->start = mbedtls_time( NULL ); |
#endif |
ssl->session_negotiate->ciphersuite = i; |
ssl->session_negotiate->compression = comp; |
ssl->session_negotiate->id_len = n; |
memcpy( ssl->session_negotiate->id, buf + 35, n ); |
} |
else |
{ |
ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; |
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( ret ); |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", |
ssl->handshake->resume ? "a" : "no" ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); |
/* |
* Perform cipher suite validation in same way as in ssl_write_client_hello. |
*/ |
i = 0; |
while( 1 ) |
{ |
if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == |
ssl->session_negotiate->ciphersuite ) |
{ |
break; |
} |
} |
suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); |
if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, ssl->minor_ver ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
ssl->handshake->ecrs_enabled = 1; |
} |
#endif |
if( comp != MBEDTLS_SSL_COMPRESS_NULL |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
&& comp != MBEDTLS_SSL_COMPRESS_DEFLATE |
#endif |
) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
ssl->session_negotiate->compression = comp; |
ext = buf + 40 + n; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); |
while( ext_len ) |
{ |
unsigned int ext_id = ( ( ext[0] << 8 ) |
| ( ext[1] ) ); |
unsigned int ext_size = ( ( ext[2] << 8 ) |
| ( ext[3] ) ); |
if( ext_size + 4 > ext_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
switch( ext_id ) |
{ |
case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
renegotiation_info_seen = 1; |
#endif |
if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, |
ext_size ) ) != 0 ) |
return( ret ); |
break; |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); |
if( ( ret = ssl_parse_max_fragment_length_ext( ssl, |
ext + 4, ext_size ) ) != 0 ) |
{ |
return( ret ); |
} |
break; |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); |
if( ( ret = ssl_parse_truncated_hmac_ext( ssl, |
ext + 4, ext_size ) ) != 0 ) |
{ |
return( ret ); |
} |
break; |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); |
if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, |
ext + 4, ext_size ) ) != 0 ) |
{ |
return( ret ); |
} |
break; |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); |
if( ( ret = ssl_parse_extended_ms_ext( ssl, |
ext + 4, ext_size ) ) != 0 ) |
{ |
return( ret ); |
} |
break; |
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
case MBEDTLS_TLS_EXT_SESSION_TICKET: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); |
if( ( ret = ssl_parse_session_ticket_ext( ssl, |
ext + 4, ext_size ) ) != 0 ) |
{ |
return( ret ); |
} |
break; |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) ); |
if( ( ret = ssl_parse_supported_point_formats_ext( ssl, |
ext + 4, ext_size ) ) != 0 ) |
{ |
return( ret ); |
} |
break; |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || |
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); |
if( ( ret = ssl_parse_ecjpake_kkpp( ssl, |
ext + 4, ext_size ) ) != 0 ) |
{ |
return( ret ); |
} |
break; |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_SSL_ALPN) |
case MBEDTLS_TLS_EXT_ALPN: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); |
if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_ALPN */ |
default: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", |
ext_id ) ); |
} |
ext_len -= 4 + ext_size; |
ext += 4 + ext_size; |
if( ext_len > 0 && ext_len < 4 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
} |
/* |
* Renegotiation security checks |
*/ |
if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && |
ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); |
handshake_failure = 1; |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && |
ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && |
renegotiation_info_seen == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); |
handshake_failure = 1; |
} |
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && |
ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && |
ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); |
handshake_failure = 1; |
} |
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && |
ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && |
renegotiation_info_seen == 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); |
handshake_failure = 1; |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
if( handshake_failure == 1 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, |
unsigned char *end ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
/* |
* Ephemeral DH parameters: |
* |
* struct { |
* opaque dh_p<1..2^16-1>; |
* opaque dh_g<1..2^16-1>; |
* opaque dh_Ys<1..2^16-1>; |
* } ServerDHParams; |
*/ |
if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); |
return( ret ); |
} |
if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", |
ssl->handshake->dhm_ctx.len * 8, |
ssl->conf->dhm_min_bitlen ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); |
return( ret ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) |
{ |
const mbedtls_ecp_curve_info *curve_info; |
mbedtls_ecp_group_id grp_id; |
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) |
grp_id = ssl->handshake->ecdh_ctx.grp.id; |
#else |
grp_id = ssl->handshake->ecdh_ctx.grp_id; |
#endif |
curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); |
if( curve_info == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); |
#if defined(MBEDTLS_ECP_C) |
if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) |
#else |
if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || |
ssl->handshake->ecdh_ctx.grp.nbits > 521 ) |
#endif |
return( -1 ); |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_QP ); |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, |
unsigned char **p, |
unsigned char *end ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
/* |
* Ephemeral ECDH parameters: |
* |
* struct { |
* ECParameters curve_params; |
* ECPoint public; |
* } ServerECDHParams; |
*/ |
if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, |
(const unsigned char **) p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; |
#endif |
return( ret ); |
} |
if( ssl_check_server_ecdh_params( ssl ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, |
unsigned char **p, |
unsigned char *end ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
size_t len; |
((void) ssl); |
/* |
* PSK parameters: |
* |
* opaque psk_identity_hint<0..2^16-1>; |
*/ |
if( end - (*p) < 2 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " |
"(psk_identity_hint length)" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
len = (*p)[0] << 8 | (*p)[1]; |
*p += 2; |
if( end - (*p) < (int) len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " |
"(psk_identity_hint length)" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
/* |
* Note: we currently ignore the PKS identity hint, as we only allow one |
* PSK to be provisionned on the client. This could be changed later if |
* someone needs that feature. |
*/ |
*p += len; |
ret = 0; |
return( ret ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
/* |
* Generate a pre-master secret and encrypt it with the server's RSA key |
*/ |
static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, |
size_t offset, size_t *olen, |
size_t pms_offset ) |
{ |
int ret; |
size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; |
unsigned char *p = ssl->handshake->premaster + pms_offset; |
if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
} |
/* |
* Generate (part of) the pre-master as |
* struct { |
* ProtocolVersion client_version; |
* opaque random[46]; |
* } PreMasterSecret; |
*/ |
mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, |
ssl->conf->transport, p ); |
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); |
return( ret ); |
} |
ssl->handshake->pmslen = 48; |
if( ssl->session_negotiate->peer_cert == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
/* |
* Now write it out, encrypted |
*/ |
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, |
MBEDTLS_PK_RSA ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); |
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); |
} |
if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, |
p, ssl->handshake->pmslen, |
ssl->out_msg + offset + len_bytes, olen, |
MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( len_bytes == 2 ) |
{ |
ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); |
ssl->out_msg[offset+1] = (unsigned char)( *olen ); |
*olen += 2; |
} |
#endif |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, |
unsigned char **p, |
unsigned char *end, |
mbedtls_md_type_t *md_alg, |
mbedtls_pk_type_t *pk_alg ) |
{ |
((void) ssl); |
*md_alg = MBEDTLS_MD_NONE; |
*pk_alg = MBEDTLS_PK_NONE; |
/* Only in TLS 1.2 */ |
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
return( 0 ); |
} |
if( (*p) + 2 > end ) |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
/* |
* Get hash algorithm |
*/ |
if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported " |
"HashAlgorithm %d", *(p)[0] ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
/* |
* Get signature algorithm |
*/ |
if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported " |
"SignatureAlgorithm %d", (*p)[1] ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
/* |
* Check if the hash is acceptable |
*/ |
if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered", |
*(p)[0] ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); |
*p += 2; |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
const mbedtls_ecp_keypair *peer_key; |
if( ssl->session_negotiate->peer_cert == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, |
MBEDTLS_PK_ECKEY ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); |
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); |
} |
peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk ); |
if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, |
MBEDTLS_ECDH_THEIRS ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); |
return( ret ); |
} |
if( ssl_check_server_ecdh_params( ssl ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || |
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
unsigned char *p = NULL, *end = NULL; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); |
ssl->state++; |
return( 0 ); |
} |
((void) p); |
((void) end); |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) |
{ |
if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); |
ssl->state++; |
return( 0 ); |
} |
((void) p); |
((void) end); |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled && |
ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) |
{ |
goto start_processing; |
} |
#endif |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
/* |
* ServerKeyExchange may be skipped with PSK and RSA-PSK when the server |
* doesn't use a psk_identity_hint |
*/ |
if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) |
{ |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) |
{ |
/* Current message is probably either |
* CertificateRequest or ServerHelloDone */ |
ssl->keep_current_message = 1; |
goto exit; |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must " |
"not be skipped" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled ) |
ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; |
start_processing: |
#endif |
p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); |
end = ssl->in_msg + ssl->in_hslen; |
MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) |
{ |
if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
} /* FALLTROUGH */ |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) |
; /* nothing more to do */ |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || |
MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) |
{ |
if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) |
{ |
if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, |
p, end - p ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) |
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) |
{ |
size_t sig_len, hashlen; |
unsigned char hash[64]; |
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; |
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; |
unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); |
size_t params_len = p - params; |
void *rs_ctx = NULL; |
/* |
* Handle the digitally-signed structure |
*/ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
if( ssl_parse_signature_algorithm( ssl, &p, end, |
&md_alg, &pk_alg ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); |
/* Default hash for ECDSA is SHA-1 */ |
if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) |
md_alg = MBEDTLS_MD_SHA1; |
} |
else |
#endif |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* |
* Read signature |
*/ |
if( p > end - 2 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
sig_len = ( p[0] << 8 ) | p[1]; |
p += 2; |
if( p != end - sig_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); |
/* |
* Compute the hash that has been signed |
*/ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( md_alg == MBEDTLS_MD_NONE ) |
{ |
hashlen = 36; |
ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params, |
params_len ); |
if( ret != 0 ) |
return( ret ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ |
MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( md_alg != MBEDTLS_MD_NONE ) |
{ |
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, |
params, params_len, |
md_alg ); |
if( ret != 0 ) |
return( ret ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); |
if( ssl->session_negotiate->peer_cert == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
/* |
* Verify signature |
*/ |
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); |
} |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled ) |
rs_ctx = &ssl->handshake->ecrs_ctx.pk; |
#endif |
if( ( ret = mbedtls_pk_verify_restartable( |
&ssl->session_negotiate->peer_cert->pk, |
md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) |
{ |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) |
#endif |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; |
#endif |
return( ret ); |
} |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ |
exit: |
ssl->state++; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); |
return( 0 ); |
} |
#if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) |
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) |
{ |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); |
if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); |
ssl->state++; |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ |
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
unsigned char *buf; |
size_t n = 0; |
size_t cert_type_len = 0, dn_len = 0; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); |
if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); |
ssl->state++; |
return( 0 ); |
} |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
ssl->state++; |
ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", |
ssl->client_auth ? "a" : "no" ) ); |
if( ssl->client_auth == 0 ) |
{ |
/* Current message is probably the ServerHelloDone */ |
ssl->keep_current_message = 1; |
goto exit; |
} |
/* |
* struct { |
* ClientCertificateType certificate_types<1..2^8-1>; |
* SignatureAndHashAlgorithm |
* supported_signature_algorithms<2^16-1>; -- TLS 1.2 only |
* DistinguishedName certificate_authorities<0..2^16-1>; |
* } CertificateRequest; |
* |
* Since we only support a single certificate on clients, let's just |
* ignore all the information that's supposed to help us pick a |
* certificate. |
* |
* We could check that our certificate matches the request, and bail out |
* if it doesn't, but it's simpler to just send the certificate anyway, |
* and give the server the opportunity to decide if it should terminate |
* the connection when it doesn't like our certificate. |
* |
* Same goes for the hash in TLS 1.2's signature_algorithms: at this |
* point we only have one hash available (see comments in |
* write_certificate_verify), so let's just use what we have. |
* |
* However, we still minimally parse the message to check it is at least |
* superficially sane. |
*/ |
buf = ssl->in_msg; |
/* certificate_types */ |
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); |
} |
cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; |
n = cert_type_len; |
/* |
* In the subsequent code there are two paths that read from buf: |
* * the length of the signature algorithms field (if minor version of |
* SSL is 3), |
* * distinguished name length otherwise. |
* Both reach at most the index: |
* ...hdr_len + 2 + n, |
* therefore the buffer length at this point must be greater than that |
* regardless of the actual code path. |
*/ |
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); |
} |
/* supported_signature_algorithms */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) |
| ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); |
#if defined(MBEDTLS_DEBUG_C) |
unsigned char* sig_alg; |
size_t i; |
#endif |
/* |
* The furthest access in buf is in the loop few lines below: |
* sig_alg[i + 1], |
* where: |
* sig_alg = buf + ...hdr_len + 3 + n, |
* max(i) = sig_alg_len - 1. |
* Therefore the furthest access is: |
* buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], |
* which reduces to: |
* buf[...hdr_len + 3 + n + sig_alg_len], |
* which is one less than we need the buf to be. |
*/ |
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n + sig_alg_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); |
} |
#if defined(MBEDTLS_DEBUG_C) |
sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; |
for( i = 0; i < sig_alg_len; i += 2 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" |
",%d", sig_alg[i], sig_alg[i + 1] ) ); |
} |
#endif |
n += 2 + sig_alg_len; |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
/* certificate_authorities */ |
dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) |
| ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); |
n += dn_len; |
if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); |
} |
exit: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ |
static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || |
ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); |
} |
ssl->state++; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
mbedtls_ssl_recv_flight_completed( ssl ); |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); |
return( 0 ); |
} |
static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
size_t i, n; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) |
{ |
/* |
* DHM key exchange -- send G^X mod P |
*/ |
n = ssl->handshake->dhm_ctx.len; |
ssl->out_msg[4] = (unsigned char)( n >> 8 ); |
ssl->out_msg[5] = (unsigned char)( n ); |
i = 6; |
ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, |
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), |
&ssl->out_msg[i], n, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); |
if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, |
ssl->handshake->premaster, |
MBEDTLS_PREMASTER_SIZE, |
&ssl->handshake->pmslen, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) |
{ |
/* |
* ECDH key exchange -- send client public value |
*/ |
i = 4; |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled ) |
{ |
if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) |
goto ecdh_calc_secret; |
mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); |
} |
#endif |
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, |
&n, |
&ssl->out_msg[i], 1000, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; |
#endif |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_Q ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled ) |
{ |
ssl->handshake->ecrs_n = n; |
ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; |
} |
ecdh_calc_secret: |
if( ssl->handshake->ecrs_enabled ) |
n = ssl->handshake->ecrs_n; |
#endif |
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, |
&ssl->handshake->pmslen, |
ssl->handshake->premaster, |
MBEDTLS_MPI_MAX_SIZE, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; |
#endif |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_Z ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) |
{ |
/* |
* opaque psk_identity<0..2^16-1>; |
*/ |
if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); |
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); |
} |
i = 4; |
n = ssl->conf->psk_identity_len; |
if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " |
"SSL buffer too short" ) ); |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
} |
ssl->out_msg[i++] = (unsigned char)( n >> 8 ); |
ssl->out_msg[i++] = (unsigned char)( n ); |
memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len ); |
i += ssl->conf->psk_identity_len; |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) |
{ |
n = 0; |
} |
else |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) |
{ |
if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) |
return( ret ); |
} |
else |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) |
{ |
/* |
* ClientDiffieHellmanPublic public (DHM send G^X mod P) |
*/ |
n = ssl->handshake->dhm_ctx.len; |
if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" |
" or SSL buffer too short" ) ); |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
} |
ssl->out_msg[i++] = (unsigned char)( n >> 8 ); |
ssl->out_msg[i++] = (unsigned char)( n ); |
ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, |
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), |
&ssl->out_msg[i], n, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) |
{ |
/* |
* ClientECDiffieHellmanPublic public; |
*/ |
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, |
&ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_Q ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, |
ciphersuite_info->key_exchange ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) |
{ |
i = 4; |
if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) |
return( ret ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
i = 4; |
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, |
ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); |
return( ret ); |
} |
ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, |
ssl->handshake->premaster, 32, &ssl->handshake->pmslen, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
{ |
((void) ciphersuite_info); |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
ssl->out_msglen = i + n; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; |
ssl->state++; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) |
{ |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); |
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); |
return( ret ); |
} |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); |
ssl->state++; |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#else |
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
size_t n = 0, offset = 0; |
unsigned char hash[48]; |
unsigned char *hash_start = hash; |
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; |
unsigned int hashlen; |
void *rs_ctx = NULL; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled && |
ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) |
{ |
goto sign; |
} |
#endif |
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); |
return( ret ); |
} |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); |
ssl->state++; |
return( 0 ); |
} |
if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); |
ssl->state++; |
return( 0 ); |
} |
if( mbedtls_ssl_own_key( ssl ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); |
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); |
} |
/* |
* Make a signature of the handshake digests |
*/ |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled ) |
ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; |
sign: |
#endif |
ssl->handshake->calc_verify( ssl, hash ); |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
/* |
* digitally-signed struct { |
* opaque md5_hash[16]; |
* opaque sha_hash[20]; |
* }; |
* |
* md5_hash |
* MD5(handshake_messages); |
* |
* sha_hash |
* SHA(handshake_messages); |
*/ |
hashlen = 36; |
md_alg = MBEDTLS_MD_NONE; |
/* |
* For ECDSA, default hash is SHA-1 only |
*/ |
if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) |
{ |
hash_start += 16; |
hashlen -= 16; |
md_alg = MBEDTLS_MD_SHA1; |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ |
MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
/* |
* digitally-signed struct { |
* opaque handshake_messages[handshake_messages_length]; |
* }; |
* |
* Taking shortcut here. We assume that the server always allows the |
* PRF Hash function and has sent it in the allowed signature |
* algorithms list received in the Certificate Request message. |
* |
* Until we encounter a server that does not, we will take this |
* shortcut. |
* |
* Reason: Otherwise we should have running hashes for SHA512 and SHA224 |
* in order to satisfy 'weird' needs from the server side. |
*/ |
if( ssl->transform_negotiate->ciphersuite_info->mac == |
MBEDTLS_MD_SHA384 ) |
{ |
md_alg = MBEDTLS_MD_SHA384; |
ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; |
} |
else |
{ |
md_alg = MBEDTLS_MD_SHA256; |
ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; |
} |
ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); |
/* Info from md_alg will be used instead */ |
hashlen = 0; |
offset = 2; |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled ) |
rs_ctx = &ssl->handshake->ecrs_ctx.pk; |
#endif |
if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), |
md_alg, hash_start, hashlen, |
ssl->out_msg + 6 + offset, &n, |
ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; |
#endif |
return( ret ); |
} |
ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); |
ssl->out_msg[5 + offset] = (unsigned char)( n ); |
ssl->out_msglen = 6 + n + offset; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; |
ssl->state++; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); |
return( ret ); |
} |
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
uint32_t lifetime; |
size_t ticket_len; |
unsigned char *ticket; |
const unsigned char *msg; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
/* |
* struct { |
* uint32 ticket_lifetime_hint; |
* opaque ticket<0..2^16-1>; |
* } NewSessionTicket; |
* |
* 0 . 3 ticket_lifetime_hint |
* 4 . 5 ticket_len (n) |
* 6 . 5+n ticket content |
*/ |
if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || |
ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); |
} |
msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); |
lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) | |
( msg[2] << 8 ) | ( msg[3] ); |
ticket_len = ( msg[4] << 8 ) | ( msg[5] ); |
if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); |
/* We're not waiting for a NewSessionTicket message any more */ |
ssl->handshake->new_session_ticket = 0; |
ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; |
/* |
* Zero-length ticket means the server changed his mind and doesn't want |
* to send a ticket after all, so just forget it |
*/ |
if( ticket_len == 0 ) |
return( 0 ); |
mbedtls_platform_zeroize( ssl->session_negotiate->ticket, |
ssl->session_negotiate->ticket_len ); |
mbedtls_free( ssl->session_negotiate->ticket ); |
ssl->session_negotiate->ticket = NULL; |
ssl->session_negotiate->ticket_len = 0; |
if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
memcpy( ticket, msg + 6, ticket_len ); |
ssl->session_negotiate->ticket = ticket; |
ssl->session_negotiate->ticket_len = ticket_len; |
ssl->session_negotiate->ticket_lifetime = lifetime; |
/* |
* RFC 5077 section 3.4: |
* "If the client receives a session ticket from the server, then it |
* discards any Session ID that was sent in the ServerHello." |
*/ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); |
ssl->session_negotiate->id_len = 0; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
/* |
* SSL handshake -- client side -- single step |
*/ |
int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) |
{ |
int ret = 0; |
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); |
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
return( ret ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) |
{ |
if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
/* Change state now, so that it is right in mbedtls_ssl_read_record(), used |
* by DTLS for dropping out-of-sequence ChangeCipherSpec records */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && |
ssl->handshake->new_session_ticket != 0 ) |
{ |
ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; |
} |
#endif |
switch( ssl->state ) |
{ |
case MBEDTLS_SSL_HELLO_REQUEST: |
ssl->state = MBEDTLS_SSL_CLIENT_HELLO; |
break; |
/* |
* ==> ClientHello |
*/ |
case MBEDTLS_SSL_CLIENT_HELLO: |
ret = ssl_write_client_hello( ssl ); |
break; |
/* |
* <== ServerHello |
* Certificate |
* ( ServerKeyExchange ) |
* ( CertificateRequest ) |
* ServerHelloDone |
*/ |
case MBEDTLS_SSL_SERVER_HELLO: |
ret = ssl_parse_server_hello( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_CERTIFICATE: |
ret = mbedtls_ssl_parse_certificate( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: |
ret = ssl_parse_server_key_exchange( ssl ); |
break; |
case MBEDTLS_SSL_CERTIFICATE_REQUEST: |
ret = ssl_parse_certificate_request( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_HELLO_DONE: |
ret = ssl_parse_server_hello_done( ssl ); |
break; |
/* |
* ==> ( Certificate/Alert ) |
* ClientKeyExchange |
* ( CertificateVerify ) |
* ChangeCipherSpec |
* Finished |
*/ |
case MBEDTLS_SSL_CLIENT_CERTIFICATE: |
ret = mbedtls_ssl_write_certificate( ssl ); |
break; |
case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: |
ret = ssl_write_client_key_exchange( ssl ); |
break; |
case MBEDTLS_SSL_CERTIFICATE_VERIFY: |
ret = ssl_write_certificate_verify( ssl ); |
break; |
case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: |
ret = mbedtls_ssl_write_change_cipher_spec( ssl ); |
break; |
case MBEDTLS_SSL_CLIENT_FINISHED: |
ret = mbedtls_ssl_write_finished( ssl ); |
break; |
/* |
* <== ( NewSessionTicket ) |
* ChangeCipherSpec |
* Finished |
*/ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: |
ret = ssl_parse_new_session_ticket( ssl ); |
break; |
#endif |
case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: |
ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_FINISHED: |
ret = mbedtls_ssl_parse_finished( ssl ); |
break; |
case MBEDTLS_SSL_FLUSH_BUFFERS: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); |
ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; |
break; |
case MBEDTLS_SSL_HANDSHAKE_WRAPUP: |
mbedtls_ssl_handshake_wrapup( ssl ); |
break; |
default: |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_CLI_C */ |
/programs/develop/libraries/kos_mbedtls/library/ssl_cookie.c |
---|
0,0 → 1,258 |
/* |
* DTLS cookie callbacks implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* These session callbacks use a simple chained list |
* to store and retrieve the session information. |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SSL_COOKIE_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/ssl_cookie.h" |
#include "mbedtls/ssl_internal.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
/* |
* If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is |
* available. Try SHA-256 first, 512 wastes resources since we need to stay |
* with max 32 bytes of cookie for DTLS 1.0 |
*/ |
#if defined(MBEDTLS_SHA256_C) |
#define COOKIE_MD MBEDTLS_MD_SHA224 |
#define COOKIE_MD_OUTLEN 32 |
#define COOKIE_HMAC_LEN 28 |
#elif defined(MBEDTLS_SHA512_C) |
#define COOKIE_MD MBEDTLS_MD_SHA384 |
#define COOKIE_MD_OUTLEN 48 |
#define COOKIE_HMAC_LEN 28 |
#elif defined(MBEDTLS_SHA1_C) |
#define COOKIE_MD MBEDTLS_MD_SHA1 |
#define COOKIE_MD_OUTLEN 20 |
#define COOKIE_HMAC_LEN 20 |
#else |
#error "DTLS hello verify needs SHA-1 or SHA-2" |
#endif |
/* |
* Cookies are formed of a 4-bytes timestamp (or serial number) and |
* an HMAC of timestemp and client ID. |
*/ |
#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) |
void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) |
{ |
mbedtls_md_init( &ctx->hmac_ctx ); |
#if !defined(MBEDTLS_HAVE_TIME) |
ctx->serial = 0; |
#endif |
ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &ctx->mutex ); |
#endif |
} |
void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) |
{ |
ctx->timeout = delay; |
} |
void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) |
{ |
mbedtls_md_free( &ctx->hmac_ctx ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &ctx->mutex ); |
#endif |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); |
} |
int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
unsigned char key[COOKIE_MD_OUTLEN]; |
if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) |
return( ret ); |
ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); |
if( ret != 0 ) |
return( ret ); |
ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); |
if( ret != 0 ) |
return( ret ); |
mbedtls_platform_zeroize( key, sizeof( key ) ); |
return( 0 ); |
} |
/* |
* Generate the HMAC part of a cookie |
*/ |
static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, |
const unsigned char time[4], |
unsigned char **p, unsigned char *end, |
const unsigned char *cli_id, size_t cli_id_len ) |
{ |
unsigned char hmac_out[COOKIE_MD_OUTLEN]; |
if( (size_t)( end - *p ) < COOKIE_HMAC_LEN ) |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || |
mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || |
mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || |
mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) |
{ |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); |
*p += COOKIE_HMAC_LEN; |
return( 0 ); |
} |
/* |
* Generate cookie for DTLS ClientHello verification |
*/ |
int mbedtls_ssl_cookie_write( void *p_ctx, |
unsigned char **p, unsigned char *end, |
const unsigned char *cli_id, size_t cli_id_len ) |
{ |
int ret; |
mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; |
unsigned long t; |
if( ctx == NULL || cli_id == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( (size_t)( end - *p ) < COOKIE_LEN ) |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
#if defined(MBEDTLS_HAVE_TIME) |
t = (unsigned long) mbedtls_time( NULL ); |
#else |
t = ctx->serial++; |
#endif |
(*p)[0] = (unsigned char)( t >> 24 ); |
(*p)[1] = (unsigned char)( t >> 16 ); |
(*p)[2] = (unsigned char)( t >> 8 ); |
(*p)[3] = (unsigned char)( t ); |
*p += 4; |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); |
#endif |
ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, |
p, end, cli_id, cli_id_len ); |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + |
MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
/* |
* Check a cookie |
*/ |
int mbedtls_ssl_cookie_check( void *p_ctx, |
const unsigned char *cookie, size_t cookie_len, |
const unsigned char *cli_id, size_t cli_id_len ) |
{ |
unsigned char ref_hmac[COOKIE_HMAC_LEN]; |
int ret = 0; |
unsigned char *p = ref_hmac; |
mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; |
unsigned long cur_time, cookie_time; |
if( ctx == NULL || cli_id == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( cookie_len != COOKIE_LEN ) |
return( -1 ); |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); |
#endif |
if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, |
&p, p + sizeof( ref_hmac ), |
cli_id, cli_id_len ) != 0 ) |
ret = -1; |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + |
MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
if( ret != 0 ) |
return( ret ); |
if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) |
return( -1 ); |
#if defined(MBEDTLS_HAVE_TIME) |
cur_time = (unsigned long) mbedtls_time( NULL ); |
#else |
cur_time = ctx->serial; |
#endif |
cookie_time = ( (unsigned long) cookie[0] << 24 ) | |
( (unsigned long) cookie[1] << 16 ) | |
( (unsigned long) cookie[2] << 8 ) | |
( (unsigned long) cookie[3] ); |
if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) |
return( -1 ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_COOKIE_C */ |
/programs/develop/libraries/kos_mbedtls/library/ssl_srv.c |
---|
0,0 → 1,4381 |
/* |
* SSLv3/TLSv1 server-side functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SSL_SRV_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/debug.h" |
#include "mbedtls/ssl.h" |
#include "mbedtls/ssl_internal.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_ECP_C) |
#include "mbedtls/ecp.h" |
#endif |
#if defined(MBEDTLS_HAVE_TIME) |
#include "mbedtls/platform_time.h" |
#endif |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) |
int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, |
const unsigned char *info, |
size_t ilen ) |
{ |
if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
mbedtls_free( ssl->cli_id ); |
if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
memcpy( ssl->cli_id, info, ilen ); |
ssl->cli_id_len = ilen; |
return( 0 ); |
} |
void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, |
mbedtls_ssl_cookie_write_t *f_cookie_write, |
mbedtls_ssl_cookie_check_t *f_cookie_check, |
void *p_cookie ) |
{ |
conf->f_cookie_write = f_cookie_write; |
conf->f_cookie_check = f_cookie_check; |
conf->p_cookie = p_cookie; |
} |
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
int ret; |
size_t servername_list_size, hostname_len; |
const unsigned char *p; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); |
if( len < 2 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); |
if( servername_list_size + 2 != len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
p = buf + 2; |
while( servername_list_size > 2 ) |
{ |
hostname_len = ( ( p[1] << 8 ) | p[2] ); |
if( hostname_len + 3 > servername_list_size ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) |
{ |
ret = ssl->conf->f_sni( ssl->conf->p_sni, |
ssl, p + 3, hostname_len ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
return( 0 ); |
} |
servername_list_size -= hostname_len + 3; |
p += hostname_len + 3; |
} |
if( servername_list_size != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ |
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
{ |
/* Check verify-data in constant-time. The length OTOH is no secret */ |
if( len != 1 + ssl->verify_data_len || |
buf[0] != ssl->verify_data_len || |
mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, |
ssl->verify_data_len ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
{ |
if( len != 1 || buf[0] != 0x0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; |
} |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
/* |
* Status of the implementation of signature-algorithms extension: |
* |
* Currently, we are only considering the signature-algorithm extension |
* to pick a ciphersuite which allows us to send the ServerKeyExchange |
* message with a signature-hash combination that the user allows. |
* |
* We do *not* check whether all certificates in our certificate |
* chain are signed with an allowed signature-hash pair. |
* This needs to be done at a later stage. |
* |
*/ |
static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
size_t sig_alg_list_size; |
const unsigned char *p; |
const unsigned char *end = buf + len; |
mbedtls_md_type_t md_cur; |
mbedtls_pk_type_t sig_cur; |
if ( len < 2 ) { |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); |
if( sig_alg_list_size + 2 != len || |
sig_alg_list_size % 2 != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* Currently we only guarantee signing the ServerKeyExchange message according |
* to the constraints specified in this extension (see above), so it suffices |
* to remember only one suitable hash for each possible signature algorithm. |
* |
* This will change when we also consider certificate signatures, |
* in which case we will need to remember the whole signature-hash |
* pair list from the extension. |
*/ |
for( p = buf + 2; p < end; p += 2 ) |
{ |
/* Silently ignore unknown signature or hash algorithms. */ |
if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" |
" unknown sig alg encoding %d", p[1] ) ); |
continue; |
} |
/* Check if we support the hash the user proposes */ |
md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); |
if( md_cur == MBEDTLS_MD_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" |
" unknown hash alg encoding %d", p[0] ) ); |
continue; |
} |
if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) |
{ |
mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" |
" match sig %d and hash %d", |
sig_cur, md_cur ) ); |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " |
"hash alg %d not supported", md_cur ) ); |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && |
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
size_t list_size, our_size; |
const unsigned char *p; |
const mbedtls_ecp_curve_info *curve_info, **curves; |
if ( len < 2 ) { |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); |
if( list_size + 2 != len || |
list_size % 2 != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* Should never happen unless client duplicates the extension */ |
if( ssl->handshake->curves != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* Don't allow our peer to make us allocate too much memory, |
* and leave room for a final 0 */ |
our_size = list_size / 2 + 1; |
if( our_size > MBEDTLS_ECP_DP_MAX ) |
our_size = MBEDTLS_ECP_DP_MAX; |
if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
ssl->handshake->curves = curves; |
p = buf + 2; |
while( list_size > 0 && our_size > 1 ) |
{ |
curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); |
if( curve_info != NULL ) |
{ |
*curves++ = curve_info; |
our_size--; |
} |
list_size -= 2; |
p += 2; |
} |
return( 0 ); |
} |
static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
size_t list_size; |
const unsigned char *p; |
if( len == 0 || (size_t)( buf[0] + 1 ) != len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
list_size = buf[0]; |
p = buf + 1; |
while( list_size > 0 ) |
{ |
if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || |
p[0] == MBEDTLS_ECP_PF_COMPRESSED ) |
{ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) |
ssl->handshake->ecdh_ctx.point_format = p[0]; |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
ssl->handshake->ecjpake_ctx.point_format = p[0]; |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); |
return( 0 ); |
} |
list_size--; |
p++; |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || |
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
int ret; |
if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); |
return( 0 ); |
} |
if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, |
buf, len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( ret ); |
} |
/* Only mark the extension as OK when we're sure it is */ |
ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
ssl->session_negotiate->mfl_code = buf[0]; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
((void) buf); |
if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) |
ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
((void) buf); |
if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && |
ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, |
size_t len ) |
{ |
if( len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
((void) buf); |
if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && |
ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t len ) |
{ |
int ret; |
mbedtls_ssl_session session; |
mbedtls_ssl_session_init( &session ); |
if( ssl->conf->f_ticket_parse == NULL || |
ssl->conf->f_ticket_write == NULL ) |
{ |
return( 0 ); |
} |
/* Remember the client asked us to send a new ticket */ |
ssl->handshake->new_session_ticket = 1; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); |
if( len == 0 ) |
return( 0 ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
/* |
* Failures are ok: just ignore the ticket and proceed. |
*/ |
if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, |
buf, len ) ) != 0 ) |
{ |
mbedtls_ssl_session_free( &session ); |
if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); |
else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); |
else |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); |
return( 0 ); |
} |
/* |
* Keep the session ID sent by the client, since we MUST send it back to |
* inform them we're accepting the ticket (RFC 5077 section 3.4) |
*/ |
session.id_len = ssl->session_negotiate->id_len; |
memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); |
mbedtls_ssl_session_free( ssl->session_negotiate ); |
memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); |
/* Zeroize instead of free as we copied the content */ |
mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); |
ssl->handshake->resume = 1; |
/* Don't send a new ticket after all, this one is OK */ |
ssl->handshake->new_session_ticket = 0; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
#if defined(MBEDTLS_SSL_ALPN) |
static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
size_t list_len, cur_len, ours_len; |
const unsigned char *theirs, *start, *end; |
const char **ours; |
/* If ALPN not configured, just ignore the extension */ |
if( ssl->conf->alpn_list == NULL ) |
return( 0 ); |
/* |
* opaque ProtocolName<1..2^8-1>; |
* |
* struct { |
* ProtocolName protocol_name_list<2..2^16-1> |
* } ProtocolNameList; |
*/ |
/* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ |
if( len < 4 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
list_len = ( buf[0] << 8 ) | buf[1]; |
if( list_len != len - 2 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* |
* Validate peer's list (lengths) |
*/ |
start = buf + 2; |
end = buf + len; |
for( theirs = start; theirs != end; theirs += cur_len ) |
{ |
cur_len = *theirs++; |
/* Current identifier must fit in list */ |
if( cur_len > (size_t)( end - theirs ) ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* Empty strings MUST NOT be included */ |
if( cur_len == 0 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
} |
/* |
* Use our order of preference |
*/ |
for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) |
{ |
ours_len = strlen( *ours ); |
for( theirs = start; theirs != end; theirs += cur_len ) |
{ |
cur_len = *theirs++; |
if( cur_len == ours_len && |
memcmp( theirs, *ours, cur_len ) == 0 ) |
{ |
ssl->alpn_chosen = *ours; |
return( 0 ); |
} |
} |
} |
/* If we get there, no match was found */ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
#endif /* MBEDTLS_SSL_ALPN */ |
/* |
* Auxiliary functions for ServerHello parsing and related actions |
*/ |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
/* |
* Return 0 if the given key uses one of the acceptable curves, -1 otherwise |
*/ |
#if defined(MBEDTLS_ECDSA_C) |
static int ssl_check_key_curve( mbedtls_pk_context *pk, |
const mbedtls_ecp_curve_info **curves ) |
{ |
const mbedtls_ecp_curve_info **crv = curves; |
mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; |
while( *crv != NULL ) |
{ |
if( (*crv)->grp_id == grp_id ) |
return( 0 ); |
crv++; |
} |
return( -1 ); |
} |
#endif /* MBEDTLS_ECDSA_C */ |
/* |
* Try picking a certificate for this ciphersuite, |
* return 0 on success and -1 on failure. |
*/ |
static int ssl_pick_cert( mbedtls_ssl_context *ssl, |
const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) |
{ |
mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; |
mbedtls_pk_type_t pk_alg = |
mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); |
uint32_t flags; |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
if( ssl->handshake->sni_key_cert != NULL ) |
list = ssl->handshake->sni_key_cert; |
else |
#endif |
list = ssl->conf->key_cert; |
if( pk_alg == MBEDTLS_PK_NONE ) |
return( 0 ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); |
if( list == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); |
return( -1 ); |
} |
for( cur = list; cur != NULL; cur = cur->next ) |
{ |
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", |
cur->cert ); |
if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); |
continue; |
} |
/* |
* This avoids sending the client a cert it'll reject based on |
* keyUsage or other extensions. |
* |
* It also allows the user to provision different certificates for |
* different uses based on keyUsage, eg if they want to avoid signing |
* and decrypting with the same RSA key. |
*/ |
if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, |
MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " |
"(extended) key usage extension" ) ); |
continue; |
} |
#if defined(MBEDTLS_ECDSA_C) |
if( pk_alg == MBEDTLS_PK_ECDSA && |
ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); |
continue; |
} |
#endif |
/* |
* Try to select a SHA-1 certificate for pre-1.2 clients, but still |
* present them a SHA-higher cert rather than failing if it's the only |
* one we got that satisfies the other conditions. |
*/ |
if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && |
cur->cert->sig_md != MBEDTLS_MD_SHA1 ) |
{ |
if( fallback == NULL ) |
fallback = cur; |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " |
"sha-2 with pre-TLS 1.2 client" ) ); |
continue; |
} |
} |
/* If we get there, we got a winner */ |
break; |
} |
if( cur == NULL ) |
cur = fallback; |
/* Do not update ssl->handshake->key_cert unless there is a match */ |
if( cur != NULL ) |
{ |
ssl->handshake->key_cert = cur; |
MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", |
ssl->handshake->key_cert->cert ); |
return( 0 ); |
} |
return( -1 ); |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
/* |
* Check if a given ciphersuite is suitable for use with our config/keys/etc |
* Sets ciphersuite_info only if the suite matches. |
*/ |
static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, |
const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) |
{ |
const mbedtls_ssl_ciphersuite_t *suite_info; |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
mbedtls_pk_type_t sig_type; |
#endif |
suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); |
if( suite_info == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) ); |
if( suite_info->min_minor_ver > ssl->minor_ver || |
suite_info->max_minor_ver < ssl->minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) |
return( 0 ); |
#endif |
#if defined(MBEDTLS_ARC4_C) |
if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && |
suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && |
( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " |
"not configured or ext missing" ) ); |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) |
if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && |
( ssl->handshake->curves == NULL || |
ssl->handshake->curves[0] == NULL ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " |
"no common elliptic curve" ) ); |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
/* If the ciphersuite requires a pre-shared key and we don't |
* have one, skip it now rather than failing later */ |
if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && |
ssl->conf->f_psk == NULL && |
( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || |
ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
/* If the ciphersuite requires signing, check whether |
* a suitable hash algorithm is present. */ |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); |
if( sig_type != MBEDTLS_PK_NONE && |
mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " |
"for signature algorithm %d", sig_type ) ); |
return( 0 ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && |
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
/* |
* Final check: if ciphersuite requires us to have a |
* certificate/key of a particular type: |
* - select the appropriate certificate if we have one, or |
* - try the next ciphersuite if we don't |
* This must be done last since we modify the key_cert list. |
*/ |
if( ssl_pick_cert( ssl, suite_info ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " |
"no suitable certificate" ) ); |
return( 0 ); |
} |
#endif |
*ciphersuite_info = suite_info; |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) |
static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) |
{ |
int ret, got_common_suite; |
unsigned int i, j; |
size_t n; |
unsigned int ciph_len, sess_len, chal_len; |
unsigned char *buf, *p; |
const int *ciphersuites; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
buf = ssl->in_hdr; |
MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", |
buf[2] ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", |
( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", |
buf[3], buf[4] ) ); |
/* |
* SSLv2 Client Hello |
* |
* Record layer: |
* 0 . 1 message length |
* |
* SSL layer: |
* 2 . 2 message type |
* 3 . 4 protocol version |
*/ |
if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || |
buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; |
if( n < 17 || n > 512 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; |
ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) |
? buf[4] : ssl->conf->max_minor_ver; |
if( ssl->minor_ver < ssl->conf->min_minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" |
" [%d:%d] < [%d:%d]", |
ssl->major_ver, ssl->minor_ver, |
ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); |
return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); |
} |
ssl->handshake->max_major_ver = buf[3]; |
ssl->handshake->max_minor_ver = buf[4]; |
if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); |
return( ret ); |
} |
ssl->handshake->update_checksum( ssl, buf + 2, n ); |
buf = ssl->in_msg; |
n = ssl->in_left - 5; |
/* |
* 0 . 1 ciphersuitelist length |
* 2 . 3 session id length |
* 4 . 5 challenge length |
* 6 . .. ciphersuitelist |
* .. . .. session id |
* .. . .. challenge |
*/ |
MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); |
ciph_len = ( buf[0] << 8 ) | buf[1]; |
sess_len = ( buf[2] << 8 ) | buf[3]; |
chal_len = ( buf[4] << 8 ) | buf[5]; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", |
ciph_len, sess_len, chal_len ) ); |
/* |
* Make sure each parameter length is valid |
*/ |
if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
if( sess_len > 32 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
if( chal_len < 8 || chal_len > 32 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
if( n != 6 + ciph_len + sess_len + chal_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", |
buf + 6, ciph_len ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", |
buf + 6 + ciph_len, sess_len ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", |
buf + 6 + ciph_len + sess_len, chal_len ); |
p = buf + 6 + ciph_len; |
ssl->session_negotiate->id_len = sess_len; |
memset( ssl->session_negotiate->id, 0, |
sizeof( ssl->session_negotiate->id ) ); |
memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); |
p += sess_len; |
memset( ssl->handshake->randbytes, 0, 64 ); |
memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); |
/* |
* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV |
*/ |
for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) |
{ |
if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " |
"during renegotiation" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; |
break; |
} |
} |
#if defined(MBEDTLS_SSL_FALLBACK_SCSV) |
for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) |
{ |
if( p[0] == 0 && |
p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && |
p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); |
if( ssl->minor_ver < ssl->conf->max_minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
break; |
} |
} |
#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ |
got_common_suite = 0; |
ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; |
ciphersuite_info = NULL; |
#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) |
for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) |
for( i = 0; ciphersuites[i] != 0; i++ ) |
#else |
for( i = 0; ciphersuites[i] != 0; i++ ) |
for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) |
#endif |
{ |
if( p[0] != 0 || |
p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || |
p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) |
continue; |
got_common_suite = 1; |
if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], |
&ciphersuite_info ) ) != 0 ) |
return( ret ); |
if( ciphersuite_info != NULL ) |
goto have_ciphersuite_v2; |
} |
if( got_common_suite ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " |
"but none of them usable" ) ); |
return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); |
return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); |
} |
have_ciphersuite_v2: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); |
ssl->session_negotiate->ciphersuite = ciphersuites[i]; |
ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; |
/* |
* SSLv2 Client Hello relevant renegotiation security checks |
*/ |
if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && |
ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
ssl->in_left = 0; |
ssl->state++; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ |
/* This function doesn't alert on errors that happen early during |
ClientHello parsing because they might indicate that the client is |
not talking SSL/TLS at all and would not understand our alert. */ |
static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) |
{ |
int ret, got_common_suite; |
size_t i, j; |
size_t ciph_offset, comp_offset, ext_offset; |
size_t msg_len, ciph_len, sess_len, comp_len, ext_len; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
size_t cookie_offset, cookie_len; |
#endif |
unsigned char *buf, *p, *ext; |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
int renegotiation_info_seen = 0; |
#endif |
int handshake_failure = 0; |
const int *ciphersuites; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info; |
int major, minor; |
/* If there is no signature-algorithm extension present, |
* we need to fall back to the default values for allowed |
* signature-hash pairs. */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
int sig_hash_alg_ext_present = 0; |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && |
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
read_record_header: |
#endif |
/* |
* If renegotiating, then the input was read with mbedtls_ssl_read_record(), |
* otherwise read it ourselves manually in order to support SSLv2 |
* ClientHello, which doesn't use the same record layer format. |
*/ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
#endif |
{ |
if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) |
{ |
/* No alert on a read error. */ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); |
return( ret ); |
} |
} |
buf = ssl->in_hdr; |
#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) |
#endif |
if( ( buf[0] & 0x80 ) != 0 ) |
return( ssl_parse_client_hello_v2( ssl ) ); |
#endif |
MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); |
/* |
* SSLv3/TLS Client Hello |
* |
* Record layer: |
* 0 . 0 message type |
* 1 . 2 protocol version |
* 3 . 11 DTLS: epoch + record sequence number |
* 3 . 4 message length |
*/ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", |
buf[0] ) ); |
if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", |
( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", |
buf[1], buf[2] ) ); |
mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); |
/* According to RFC 5246 Appendix E.1, the version here is typically |
* "{03,00}, the lowest version number supported by the client, [or] the |
* value of ClientHello.client_version", so the only meaningful check here |
* is the major version shouldn't be less than 3 */ |
if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* For DTLS if this is the initial handshake, remember the client sequence |
* number to use it in our next message (RFC 6347 4.2.1) */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
&& ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE |
#endif |
) |
{ |
/* Epoch should be 0 for initial handshakes */ |
if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 ); |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); |
ssl->next_record_offset = 0; |
ssl->in_left = 0; |
goto read_record_header; |
} |
/* No MAC to check yet, so we can update right now */ |
mbedtls_ssl_dtls_replay_update( ssl ); |
#endif |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
{ |
/* Set by mbedtls_ssl_read_record() */ |
msg_len = ssl->in_hslen; |
} |
else |
#endif |
{ |
if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
if( ( ret = mbedtls_ssl_fetch_input( ssl, |
mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); |
return( ret ); |
} |
/* Done reading this record, get ready for the next one */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl ); |
else |
#endif |
ssl->in_left = 0; |
} |
buf = ssl->in_msg; |
MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); |
ssl->handshake->update_checksum( ssl, buf, msg_len ); |
/* |
* Handshake layer: |
* 0 . 0 handshake type |
* 1 . 3 handshake length |
* 4 . 5 DTLS only: message seqence number |
* 6 . 8 DTLS only: fragment offset |
* 9 . 11 DTLS only: fragment length |
*/ |
if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); |
if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", |
( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); |
/* We don't support fragmentation of ClientHello (yet?) */ |
if( buf[1] != 0 || |
msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
/* |
* Copy the client's handshake message_seq on initial handshakes, |
* check sequence number on renego. |
*/ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
{ |
/* This couldn't be done in ssl_prepare_handshake_record() */ |
unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | |
ssl->in_msg[5]; |
if( cli_msg_seq != ssl->handshake->in_msg_seq ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " |
"%d (expected %d)", cli_msg_seq, |
ssl->handshake->in_msg_seq ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
ssl->handshake->in_msg_seq++; |
} |
else |
#endif |
{ |
unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | |
ssl->in_msg[5]; |
ssl->handshake->out_msg_seq = cli_msg_seq; |
ssl->handshake->in_msg_seq = cli_msg_seq + 1; |
} |
/* |
* For now we don't support fragmentation, so make sure |
* fragment_offset == 0 and fragment_length == length |
*/ |
if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || |
memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); |
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
buf += mbedtls_ssl_hs_hdr_len( ssl ); |
msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); |
/* |
* ClientHello layer: |
* 0 . 1 protocol version |
* 2 . 33 random bytes (starting with 4 bytes of Unix time) |
* 34 . 35 session id length (1 byte) |
* 35 . 34+x session id |
* 35+x . 35+x DTLS only: cookie length (1 byte) |
* 36+x . .. DTLS only: cookie |
* .. . .. ciphersuite list length (2 bytes) |
* .. . .. ciphersuite list |
* .. . .. compression alg. list length (1 byte) |
* .. . .. compression alg. list |
* .. . .. extensions length (2 bytes, optional) |
* .. . .. extensions (optional) |
*/ |
/* |
* Minimal length (with everything empty and extensions omitted) is |
* 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can |
* read at least up to session id length without worrying. |
*/ |
if( msg_len < 38 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* |
* Check and save the protocol version |
*/ |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); |
mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, |
ssl->conf->transport, buf ); |
ssl->handshake->max_major_ver = ssl->major_ver; |
ssl->handshake->max_minor_ver = ssl->minor_ver; |
if( ssl->major_ver < ssl->conf->min_major_ver || |
ssl->minor_ver < ssl->conf->min_minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" |
" [%d:%d] < [%d:%d]", |
ssl->major_ver, ssl->minor_ver, |
ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); |
return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); |
} |
if( ssl->major_ver > ssl->conf->max_major_ver ) |
{ |
ssl->major_ver = ssl->conf->max_major_ver; |
ssl->minor_ver = ssl->conf->max_minor_ver; |
} |
else if( ssl->minor_ver > ssl->conf->max_minor_ver ) |
ssl->minor_ver = ssl->conf->max_minor_ver; |
/* |
* Save client random (inc. Unix time) |
*/ |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); |
memcpy( ssl->handshake->randbytes, buf + 2, 32 ); |
/* |
* Check the session ID length and save session ID |
*/ |
sess_len = buf[34]; |
if( sess_len > sizeof( ssl->session_negotiate->id ) || |
sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); |
ssl->session_negotiate->id_len = sess_len; |
memset( ssl->session_negotiate->id, 0, |
sizeof( ssl->session_negotiate->id ) ); |
memcpy( ssl->session_negotiate->id, buf + 35, |
ssl->session_negotiate->id_len ); |
/* |
* Check the cookie length and content |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
cookie_offset = 35 + sess_len; |
cookie_len = buf[cookie_offset]; |
if( cookie_offset + 1 + cookie_len + 2 > msg_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", |
buf + cookie_offset + 1, cookie_len ); |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) |
if( ssl->conf->f_cookie_check != NULL |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
&& ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE |
#endif |
) |
{ |
if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, |
buf + cookie_offset + 1, cookie_len, |
ssl->cli_id, ssl->cli_id_len ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); |
ssl->handshake->verify_cookie_len = 1; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); |
ssl->handshake->verify_cookie_len = 0; |
} |
} |
else |
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ |
{ |
/* We know we didn't send a cookie, so it should be empty */ |
if( cookie_len != 0 ) |
{ |
/* This may be an attacker's probe, so don't send an alert */ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); |
} |
/* |
* Check the ciphersuitelist length (will be parsed later) |
*/ |
ciph_offset = cookie_offset + 1 + cookie_len; |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
ciph_offset = 35 + sess_len; |
ciph_len = ( buf[ciph_offset + 0] << 8 ) |
| ( buf[ciph_offset + 1] ); |
if( ciph_len < 2 || |
ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ |
( ciph_len % 2 ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", |
buf + ciph_offset + 2, ciph_len ); |
/* |
* Check the compression algorithms length and pick one |
*/ |
comp_offset = ciph_offset + 2 + ciph_len; |
comp_len = buf[comp_offset]; |
if( comp_len < 1 || |
comp_len > 16 || |
comp_len + comp_offset + 1 > msg_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", |
buf + comp_offset + 1, comp_len ); |
ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
for( i = 0; i < comp_len; ++i ) |
{ |
if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) |
{ |
ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; |
break; |
} |
} |
#endif |
/* See comments in ssl_write_client_hello() */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; |
#endif |
/* Do not parse the extensions if the protocol is SSLv3 */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) |
{ |
#endif |
/* |
* Check the extension length |
*/ |
ext_offset = comp_offset + 1 + comp_len; |
if( msg_len > ext_offset ) |
{ |
if( msg_len < ext_offset + 2 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
ext_len = ( buf[ext_offset + 0] << 8 ) |
| ( buf[ext_offset + 1] ); |
if( ( ext_len > 0 && ext_len < 4 ) || |
msg_len != ext_offset + 2 + ext_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
} |
else |
ext_len = 0; |
ext = buf + ext_offset + 2; |
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); |
while( ext_len != 0 ) |
{ |
unsigned int ext_id; |
unsigned int ext_size; |
if ( ext_len < 4 ) { |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); |
ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); |
if( ext_size + 4 > ext_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
switch( ext_id ) |
{ |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
case MBEDTLS_TLS_EXT_SERVERNAME: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); |
if( ssl->conf->f_sni == NULL ) |
break; |
ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ |
case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
renegotiation_info_seen = 1; |
#endif |
ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
case MBEDTLS_TLS_EXT_SIG_ALG: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); |
ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
sig_hash_alg_ext_present = 1; |
break; |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && |
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); |
ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); |
ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; |
ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || |
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); |
ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); |
ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); |
ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); |
ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); |
ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
case MBEDTLS_TLS_EXT_SESSION_TICKET: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); |
ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
#if defined(MBEDTLS_SSL_ALPN) |
case MBEDTLS_TLS_EXT_ALPN: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); |
ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); |
if( ret != 0 ) |
return( ret ); |
break; |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
default: |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", |
ext_id ) ); |
} |
ext_len -= 4 + ext_size; |
ext += 4 + ext_size; |
if( ext_len > 0 && ext_len < 4 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
} |
#endif |
#if defined(MBEDTLS_SSL_FALLBACK_SCSV) |
for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) |
{ |
if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && |
p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); |
if( ssl->minor_ver < ssl->conf->max_minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
break; |
} |
} |
#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
/* |
* Try to fall back to default hash SHA1 if the client |
* hasn't provided any preferred signature-hash combinations. |
*/ |
if( sig_hash_alg_ext_present == 0 ) |
{ |
mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; |
if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) |
md_default = MBEDTLS_MD_NONE; |
mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && |
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
/* |
* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV |
*/ |
for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) |
{ |
if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " |
"during renegotiation" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
#endif |
ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; |
break; |
} |
} |
/* |
* Renegotiation security checks |
*/ |
if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && |
ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); |
handshake_failure = 1; |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && |
ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && |
renegotiation_info_seen == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); |
handshake_failure = 1; |
} |
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && |
ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && |
ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); |
handshake_failure = 1; |
} |
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && |
ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && |
renegotiation_info_seen == 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); |
handshake_failure = 1; |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
if( handshake_failure == 1 ) |
{ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
/* |
* Search for a matching ciphersuite |
* (At the end because we need information from the EC-based extensions |
* and certificate from the SNI callback triggered by the SNI extension.) |
*/ |
got_common_suite = 0; |
ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; |
ciphersuite_info = NULL; |
#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) |
for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) |
for( i = 0; ciphersuites[i] != 0; i++ ) |
#else |
for( i = 0; ciphersuites[i] != 0; i++ ) |
for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) |
#endif |
{ |
if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || |
p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) |
continue; |
got_common_suite = 1; |
if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], |
&ciphersuite_info ) ) != 0 ) |
return( ret ); |
if( ciphersuite_info != NULL ) |
goto have_ciphersuite; |
} |
if( got_common_suite ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " |
"but none of them usable" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); |
return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); |
} |
have_ciphersuite: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); |
ssl->session_negotiate->ciphersuite = ciphersuites[i]; |
ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; |
ssl->state++; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
mbedtls_ssl_recv_flight_completed( ssl ); |
#endif |
/* Debugging-only output for testsuite */ |
#if defined(MBEDTLS_DEBUG_C) && \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); |
if( sig_alg != MBEDTLS_PK_NONE ) |
{ |
mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, |
sig_alg ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", |
mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " |
"%d - should not happen", sig_alg ) ); |
} |
} |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 0x00; |
*olen = 4; |
} |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
const mbedtls_ssl_ciphersuite_t *suite = NULL; |
const mbedtls_cipher_info_t *cipher = NULL; |
if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
*olen = 0; |
return; |
} |
/* |
* RFC 7366: "If a server receives an encrypt-then-MAC request extension |
* from a client and then selects a stream or Authenticated Encryption |
* with Associated Data (AEAD) ciphersuite, it MUST NOT send an |
* encrypt-then-MAC response extension back to the client." |
*/ |
if( ( suite = mbedtls_ssl_ciphersuite_from_id( |
ssl->session_negotiate->ciphersuite ) ) == NULL || |
( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || |
cipher->mode != MBEDTLS_MODE_CBC ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 0x00; |
*olen = 4; |
} |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " |
"extension" ) ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 0x00; |
*olen = 4; |
} |
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
if( ssl->handshake->new_session_ticket == 0 ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 0x00; |
*olen = 4; |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) |
{ |
*p++ = 0x00; |
*p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; |
*p++ = ssl->verify_data_len * 2 & 0xFF; |
memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); |
p += ssl->verify_data_len; |
memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); |
p += ssl->verify_data_len; |
} |
else |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
{ |
*p++ = 0x00; |
*p++ = 0x01; |
*p++ = 0x00; |
} |
*olen = p - buf; |
} |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 1; |
*p++ = ssl->session_negotiate->mfl_code; |
*olen = 5; |
} |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
((void) ssl); |
if( ( ssl->handshake->cli_exts & |
MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); |
*p++ = 0x00; |
*p++ = 2; |
*p++ = 1; |
*p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; |
*olen = 6; |
} |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, |
size_t *olen ) |
{ |
int ret; |
unsigned char *p = buf; |
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
size_t kkpp_len; |
*olen = 0; |
/* Skip costly computation if not needed */ |
if( ssl->transform_negotiate->ciphersuite_info->key_exchange != |
MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
return; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); |
if( end - p < 4 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); |
return; |
} |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); |
ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, |
p + 2, end - p - 2, &kkpp_len, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); |
return; |
} |
*p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); |
*olen = kkpp_len + 4; |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_SSL_ALPN ) |
static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, |
unsigned char *buf, size_t *olen ) |
{ |
if( ssl->alpn_chosen == NULL ) |
{ |
*olen = 0; |
return; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); |
/* |
* 0 . 1 ext identifier |
* 2 . 3 ext length |
* 4 . 5 protocol list length |
* 6 . 6 protocol name length |
* 7 . 7+n protocol name |
*/ |
buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); |
buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); |
*olen = 7 + strlen( ssl->alpn_chosen ); |
buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); |
buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); |
buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); |
buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); |
buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); |
memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); |
} |
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) |
static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
unsigned char *p = ssl->out_msg + 4; |
unsigned char *cookie_len_byte; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); |
/* |
* struct { |
* ProtocolVersion server_version; |
* opaque cookie<0..2^8-1>; |
* } HelloVerifyRequest; |
*/ |
/* The RFC is not clear on this point, but sending the actual negotiated |
* version looks like the most interoperable thing to do. */ |
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, |
ssl->conf->transport, p ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); |
p += 2; |
/* If we get here, f_cookie_check is not null */ |
if( ssl->conf->f_cookie_write == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* Skip length byte until we know the length */ |
cookie_len_byte = p++; |
if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, |
&p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, |
ssl->cli_id, ssl->cli_id_len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); |
return( ret ); |
} |
*cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); |
ssl->out_msglen = p - ssl->out_msg; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; |
ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ |
static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) |
{ |
#if defined(MBEDTLS_HAVE_TIME) |
mbedtls_time_t t; |
#endif |
int ret; |
size_t olen, ext_len = 0, n; |
unsigned char *buf, *p; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake->verify_cookie_len != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); |
return( ssl_write_hello_verify_request( ssl ) ); |
} |
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ |
if( ssl->conf->f_rng == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); |
return( MBEDTLS_ERR_SSL_NO_RNG ); |
} |
/* |
* 0 . 0 handshake type |
* 1 . 3 handshake length |
* 4 . 5 protocol version |
* 6 . 9 UNIX time() |
* 10 . 37 random bytes |
*/ |
buf = ssl->out_msg; |
p = buf + 4; |
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, |
ssl->conf->transport, p ); |
p += 2; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", |
buf[4], buf[5] ) ); |
#if defined(MBEDTLS_HAVE_TIME) |
t = mbedtls_time( NULL ); |
*p++ = (unsigned char)( t >> 24 ); |
*p++ = (unsigned char)( t >> 16 ); |
*p++ = (unsigned char)( t >> 8 ); |
*p++ = (unsigned char)( t ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); |
#else |
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) |
return( ret ); |
p += 4; |
#endif /* MBEDTLS_HAVE_TIME */ |
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) |
return( ret ); |
p += 28; |
memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); |
/* |
* Resume is 0 by default, see ssl_handshake_init(). |
* It may be already set to 1 by ssl_parse_session_ticket_ext(). |
* If not, try looking up session ID in our cache. |
*/ |
if( ssl->handshake->resume == 0 && |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && |
#endif |
ssl->session_negotiate->id_len != 0 && |
ssl->conf->f_get_cache != NULL && |
ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); |
ssl->handshake->resume = 1; |
} |
if( ssl->handshake->resume == 0 ) |
{ |
/* |
* New session, create a new session id, |
* unless we're about to issue a session ticket |
*/ |
ssl->state++; |
#if defined(MBEDTLS_HAVE_TIME) |
ssl->session_negotiate->start = mbedtls_time( NULL ); |
#endif |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
if( ssl->handshake->new_session_ticket != 0 ) |
{ |
ssl->session_negotiate->id_len = n = 0; |
memset( ssl->session_negotiate->id, 0, 32 ); |
} |
else |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
{ |
ssl->session_negotiate->id_len = n = 32; |
if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, |
n ) ) != 0 ) |
return( ret ); |
} |
} |
else |
{ |
/* |
* Resuming a session |
*/ |
n = ssl->session_negotiate->id_len; |
ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; |
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); |
return( ret ); |
} |
} |
/* |
* 38 . 38 session id length |
* 39 . 38+n session id |
* 39+n . 40+n chosen ciphersuite |
* 41+n . 41+n chosen compression alg. |
* 42+n . 43+n extensions length |
* 44+n . 43+n+m extensions |
*/ |
*p++ = (unsigned char) ssl->session_negotiate->id_len; |
memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); |
p += ssl->session_negotiate->id_len; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", |
ssl->handshake->resume ? "a" : "no" ) ); |
*p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); |
*p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); |
*p++ = (unsigned char)( ssl->session_negotiate->compression ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", |
mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", |
ssl->session_negotiate->compression ) ); |
/* Do not write the extensions if the protocol is SSLv3 */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) |
{ |
#endif |
/* |
* First write extensions, then the total length |
*/ |
ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if ( mbedtls_ssl_ciphersuite_uses_ec( |
mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) |
{ |
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
} |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
#if defined(MBEDTLS_SSL_ALPN) |
ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); |
ext_len += olen; |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); |
if( ext_len > 0 ) |
{ |
*p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( ext_len ) & 0xFF ); |
p += ext_len; |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
} |
#endif |
ssl->out_msglen = p - buf; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; |
ret = mbedtls_ssl_write_handshake_msg( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); |
return( ret ); |
} |
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) |
{ |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); |
ssl->state++; |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#else |
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
size_t dn_size, total_dn_size; /* excluding length bytes */ |
size_t ct_len, sa_len; /* including length bytes */ |
unsigned char *buf, *p; |
const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; |
const mbedtls_x509_crt *crt; |
int authmode; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); |
ssl->state++; |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) |
authmode = ssl->handshake->sni_authmode; |
else |
#endif |
authmode = ssl->conf->authmode; |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || |
authmode == MBEDTLS_SSL_VERIFY_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); |
return( 0 ); |
} |
/* |
* 0 . 0 handshake type |
* 1 . 3 handshake length |
* 4 . 4 cert type count |
* 5 .. m-1 cert types |
* m .. m+1 sig alg length (TLS 1.2 only) |
* m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) |
* n .. n+1 length of all DNs |
* n+2 .. n+3 length of DN 1 |
* n+4 .. ... Distinguished Name #1 |
* ... .. ... length of DN 2, etc. |
*/ |
buf = ssl->out_msg; |
p = buf + 4; |
/* |
* Supported certificate types |
* |
* ClientCertificateType certificate_types<1..2^8-1>; |
* enum { (255) } ClientCertificateType; |
*/ |
ct_len = 0; |
#if defined(MBEDTLS_RSA_C) |
p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; |
#endif |
p[0] = (unsigned char) ct_len++; |
p += ct_len; |
sa_len = 0; |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
/* |
* Add signature_algorithms for verify (TLS 1.2) |
* |
* SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; |
* |
* struct { |
* HashAlgorithm hash; |
* SignatureAlgorithm signature; |
* } SignatureAndHashAlgorithm; |
* |
* enum { (255) } HashAlgorithm; |
* enum { (255) } SignatureAlgorithm; |
*/ |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
const int *cur; |
/* |
* Supported signature algorithms |
*/ |
for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) |
{ |
unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); |
if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) |
continue; |
#if defined(MBEDTLS_RSA_C) |
p[2 + sa_len++] = hash; |
p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
p[2 + sa_len++] = hash; |
p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; |
#endif |
} |
p[0] = (unsigned char)( sa_len >> 8 ); |
p[1] = (unsigned char)( sa_len ); |
sa_len += 2; |
p += sa_len; |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
/* |
* DistinguishedName certificate_authorities<0..2^16-1>; |
* opaque DistinguishedName<1..2^16-1>; |
*/ |
p += 2; |
total_dn_size = 0; |
if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) |
{ |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
if( ssl->handshake->sni_ca_chain != NULL ) |
crt = ssl->handshake->sni_ca_chain; |
else |
#endif |
crt = ssl->conf->ca_chain; |
while( crt != NULL && crt->version != 0 ) |
{ |
dn_size = crt->subject_raw.len; |
if( end < p || |
(size_t)( end - p ) < dn_size || |
(size_t)( end - p ) < 2 + dn_size ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); |
break; |
} |
*p++ = (unsigned char)( dn_size >> 8 ); |
*p++ = (unsigned char)( dn_size ); |
memcpy( p, crt->subject_raw.p, dn_size ); |
p += dn_size; |
MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); |
total_dn_size += 2 + dn_size; |
crt = crt->next; |
} |
} |
ssl->out_msglen = p - buf; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; |
ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); |
ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); |
ret = mbedtls_ssl_write_handshake_msg( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); |
return( ret ); |
} |
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); |
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); |
} |
if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, |
mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), |
MBEDTLS_ECDH_OURS ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || |
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ |
defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, |
size_t *signature_len ) |
{ |
/* Append the signature to ssl->out_msg, leaving 2 bytes for the |
* signature length which will be added in ssl_write_server_key_exchange |
* after the call to ssl_prepare_server_key_exchange. |
* ssl_write_server_key_exchange also takes care of incrementing |
* ssl->out_msglen. */ |
unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; |
size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN |
- sig_start ); |
int ret = ssl->conf->f_async_resume( ssl, |
sig_start, signature_len, sig_max_len ); |
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) |
{ |
ssl->handshake->async_in_progress = 0; |
mbedtls_ssl_set_async_operation_data( ssl, NULL ); |
} |
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); |
return( ret ); |
} |
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && |
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ |
/* Prepare the ServerKeyExchange message, up to and including |
* calculating the signature if any, but excluding formatting the |
* signature and sending the message. */ |
static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, |
size_t *signature_len ) |
{ |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) |
unsigned char *dig_signed = NULL; |
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ |
(void) ciphersuite_info; /* unused in some configurations */ |
#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) |
(void) signature_len; |
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ |
ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ |
/* |
* |
* Part 1: Provide key exchange parameters for chosen ciphersuite. |
* |
*/ |
/* |
* - ECJPAKE key exchanges |
*/ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
int ret; |
size_t len = 0; |
ret = mbedtls_ecjpake_write_round_two( |
&ssl->handshake->ecjpake_ctx, |
ssl->out_msg + ssl->out_msglen, |
MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); |
return( ret ); |
} |
ssl->out_msglen += len; |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
/* |
* For (EC)DHE key exchanges with PSK, parameters are prefixed by support |
* identity hint (RFC 4279, Sec. 3). Until someone needs this feature, |
* we use empty support identity hints here. |
**/ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) |
{ |
ssl->out_msg[ssl->out_msglen++] = 0x00; |
ssl->out_msg[ssl->out_msglen++] = 0x00; |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
/* |
* - DHE key exchanges |
*/ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) |
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) |
{ |
int ret; |
size_t len = 0; |
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
/* |
* Ephemeral DH parameters: |
* |
* struct { |
* opaque dh_p<1..2^16-1>; |
* opaque dh_g<1..2^16-1>; |
* opaque dh_Ys<1..2^16-1>; |
* } ServerDHParams; |
*/ |
if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, |
&ssl->conf->dhm_P, |
&ssl->conf->dhm_G ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_dhm_make_params( |
&ssl->handshake->dhm_ctx, |
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), |
ssl->out_msg + ssl->out_msglen, &len, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) |
dig_signed = ssl->out_msg + ssl->out_msglen; |
#endif |
ssl->out_msglen += len; |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */ |
/* |
* - ECDHE key exchanges |
*/ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) |
if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) |
{ |
/* |
* Ephemeral ECDH parameters: |
* |
* struct { |
* ECParameters curve_params; |
* ECPoint public; |
* } ServerECDHParams; |
*/ |
const mbedtls_ecp_curve_info **curve = NULL; |
const mbedtls_ecp_group_id *gid; |
int ret; |
size_t len = 0; |
/* Match our preference list against the offered curves */ |
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) |
for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) |
if( (*curve)->grp_id == *gid ) |
goto curve_matching_done; |
curve_matching_done: |
if( curve == NULL || *curve == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); |
return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); |
if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx, |
(*curve)->grp_id ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_ecdh_make_params( |
&ssl->handshake->ecdh_ctx, &len, |
ssl->out_msg + ssl->out_msglen, |
MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) |
dig_signed = ssl->out_msg + ssl->out_msglen; |
#endif |
ssl->out_msglen += len; |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_Q ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ |
/* |
* |
* Part 2: For key exchanges involving the server signing the |
* exchange parameters, compute and add the signature here. |
* |
*/ |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) |
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) |
{ |
size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; |
size_t hashlen = 0; |
unsigned char hash[MBEDTLS_MD_MAX_SIZE]; |
int ret; |
/* |
* 2.1: Choose hash algorithm: |
* A: For TLS 1.2, obey signature-hash-algorithm extension |
* to choose appropriate hash. |
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 |
* (RFC 4492, Sec. 5.4) |
* C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) |
*/ |
mbedtls_md_type_t md_alg; |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
mbedtls_pk_type_t sig_alg = |
mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
/* A: For TLS 1.2, obey signature-hash-algorithm extension |
* (RFC 5246, Sec. 7.4.1.4.1). */ |
if( sig_alg == MBEDTLS_PK_NONE || |
( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, |
sig_alg ) ) == MBEDTLS_MD_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
/* (... because we choose a cipher suite |
* only if there is a matching hash.) */ |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) |
{ |
/* B: Default hash SHA1 */ |
md_alg = MBEDTLS_MD_SHA1; |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ |
MBEDTLS_SSL_PROTO_TLS1_1 */ |
{ |
/* C: MD5 + SHA1 */ |
md_alg = MBEDTLS_MD_NONE; |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); |
/* |
* 2.2: Compute the hash to be signed |
*/ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( md_alg == MBEDTLS_MD_NONE ) |
{ |
hashlen = 36; |
ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, |
dig_signed, |
dig_signed_len ); |
if( ret != 0 ) |
return( ret ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ |
MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( md_alg != MBEDTLS_MD_NONE ) |
{ |
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, |
dig_signed, |
dig_signed_len, |
md_alg ); |
if( ret != 0 ) |
return( ret ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); |
/* |
* 2.3: Compute and add the signature |
*/ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
/* |
* For TLS 1.2, we need to specify signature and hash algorithm |
* explicitly through a prefix to the signature. |
* |
* struct { |
* HashAlgorithm hash; |
* SignatureAlgorithm signature; |
* } SignatureAndHashAlgorithm; |
* |
* struct { |
* SignatureAndHashAlgorithm algorithm; |
* opaque signature<0..2^16-1>; |
* } DigitallySigned; |
* |
*/ |
ssl->out_msg[ssl->out_msglen++] = |
mbedtls_ssl_hash_from_md_alg( md_alg ); |
ssl->out_msg[ssl->out_msglen++] = |
mbedtls_ssl_sig_from_pk_alg( sig_alg ); |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
if( ssl->conf->f_async_sign_start != NULL ) |
{ |
ret = ssl->conf->f_async_sign_start( ssl, |
mbedtls_ssl_own_cert( ssl ), |
md_alg, hash, hashlen ); |
switch( ret ) |
{ |
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: |
/* act as if f_async_sign was null */ |
break; |
case 0: |
ssl->handshake->async_in_progress = 1; |
return( ssl_resume_server_key_exchange( ssl, signature_len ) ); |
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: |
ssl->handshake->async_in_progress = 1; |
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); |
default: |
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); |
return( ret ); |
} |
} |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
if( mbedtls_ssl_own_key( ssl ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); |
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); |
} |
/* Append the signature to ssl->out_msg, leaving 2 bytes for the |
* signature length which will be added in ssl_write_server_key_exchange |
* after the call to ssl_prepare_server_key_exchange. |
* ssl_write_server_key_exchange also takes care of incrementing |
* ssl->out_msglen. */ |
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), |
md_alg, hash, hashlen, |
ssl->out_msg + ssl->out_msglen + 2, |
signature_len, |
ssl->conf->f_rng, |
ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); |
return( ret ); |
} |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ |
return( 0 ); |
} |
/* Prepare the ServerKeyExchange message and send it. For ciphersuites |
* that do not include a ServerKeyExchange message, do nothing. Either |
* way, if successful, move on to the next step in the SSL state |
* machine. */ |
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
size_t signature_len = 0; |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) |
/* Extract static ECDH parameters and abort if ServerKeyExchange |
* is not needed. */ |
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) |
{ |
/* For suites involving ECDH, extract DH parameters |
* from certificate at this point. */ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) |
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) |
{ |
ssl_get_ecdh_params_from_cert( ssl ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ |
/* Key exchanges not involving ephemeral keys don't use |
* ServerKeyExchange, so end here. */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); |
ssl->state++; |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ |
defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
/* If we have already prepared the message and there is an ongoing |
* signature operation, resume signing. */ |
if( ssl->handshake->async_in_progress != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); |
ret = ssl_resume_server_key_exchange( ssl, &signature_len ); |
} |
else |
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && |
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ |
{ |
/* ServerKeyExchange is needed. Prepare the message. */ |
ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); |
} |
if( ret != 0 ) |
{ |
/* If we're starting to write a new message, set ssl->out_msglen |
* to 0. But if we're resuming after an asynchronous message, |
* out_msglen is the amount of data written so far and mst be |
* preserved. */ |
if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); |
else |
ssl->out_msglen = 0; |
return( ret ); |
} |
/* If there is a signature, write its length. |
* ssl_prepare_server_key_exchange already wrote the signature |
* itself at its proper place in the output buffer. */ |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) |
if( signature_len != 0 ) |
{ |
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 ); |
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", |
ssl->out_msg + ssl->out_msglen, |
signature_len ); |
/* Skip over the already-written signature */ |
ssl->out_msglen += signature_len; |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ |
/* Add header and send. */ |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; |
ssl->state++; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); |
return( 0 ); |
} |
static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); |
ssl->out_msglen = 4; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; |
ssl->state++; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
mbedtls_ssl_send_flight_completed( ssl ); |
#endif |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, |
const unsigned char *end ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
size_t n; |
/* |
* Receive G^Y mod P, premaster = (G^Y)^X mod P |
*/ |
if( *p + 2 > end ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
n = ( (*p)[0] << 8 ) | (*p)[1]; |
*p += 2; |
if( *p + n > end ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); |
} |
*p += n; |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); |
return( ret ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, |
unsigned char *peer_pms, |
size_t *peer_pmslen, |
size_t peer_pmssize ) |
{ |
int ret = ssl->conf->f_async_resume( ssl, |
peer_pms, peer_pmslen, peer_pmssize ); |
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) |
{ |
ssl->handshake->async_in_progress = 0; |
mbedtls_ssl_set_async_operation_data( ssl, NULL ); |
} |
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, |
const unsigned char *p, |
const unsigned char *end, |
unsigned char *peer_pms, |
size_t *peer_pmslen, |
size_t peer_pmssize ) |
{ |
int ret; |
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); |
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; |
size_t len = mbedtls_pk_get_len( public_key ); |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
/* If we have already started decoding the message and there is an ongoing |
* decryption operation, resume signing. */ |
if( ssl->handshake->async_in_progress != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); |
return( ssl_resume_decrypt_pms( ssl, |
peer_pms, peer_pmslen, peer_pmssize ) ); |
} |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
/* |
* Prepare to decrypt the premaster using own private RSA key |
*/ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
if ( p + 2 > end ) { |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
if( *p++ != ( ( len >> 8 ) & 0xFF ) || |
*p++ != ( ( len ) & 0xFF ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
} |
#endif |
if( p + len != end ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
/* |
* Decrypt the premaster secret |
*/ |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
if( ssl->conf->f_async_decrypt_start != NULL ) |
{ |
ret = ssl->conf->f_async_decrypt_start( ssl, |
mbedtls_ssl_own_cert( ssl ), |
p, len ); |
switch( ret ) |
{ |
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: |
/* act as if f_async_decrypt_start was null */ |
break; |
case 0: |
ssl->handshake->async_in_progress = 1; |
return( ssl_resume_decrypt_pms( ssl, |
peer_pms, |
peer_pmslen, |
peer_pmssize ) ); |
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: |
ssl->handshake->async_in_progress = 1; |
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); |
default: |
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); |
return( ret ); |
} |
} |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); |
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); |
} |
ret = mbedtls_pk_decrypt( private_key, p, len, |
peer_pms, peer_pmslen, peer_pmssize, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
return( ret ); |
} |
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, |
const unsigned char *p, |
const unsigned char *end, |
size_t pms_offset ) |
{ |
int ret; |
unsigned char *pms = ssl->handshake->premaster + pms_offset; |
unsigned char ver[2]; |
unsigned char fake_pms[48], peer_pms[48]; |
unsigned char mask; |
size_t i, peer_pmslen; |
unsigned int diff; |
/* In case of a failure in decryption, the decryption may write less than |
* 2 bytes of output, but we always read the first two bytes. It doesn't |
* matter in the end because diff will be nonzero in that case due to |
* peer_pmslen being less than 48, and we only care whether diff is 0. |
* But do initialize peer_pms for robustness anyway. This also makes |
* memory analyzers happy (don't access uninitialized memory, even |
* if it's an unsigned char). */ |
peer_pms[0] = peer_pms[1] = ~0; |
ret = ssl_decrypt_encrypted_pms( ssl, p, end, |
peer_pms, |
&peer_pmslen, |
sizeof( peer_pms ) ); |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) |
return( ret ); |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
mbedtls_ssl_write_version( ssl->handshake->max_major_ver, |
ssl->handshake->max_minor_ver, |
ssl->conf->transport, ver ); |
/* Avoid data-dependent branches while checking for invalid |
* padding, to protect against timing-based Bleichenbacher-type |
* attacks. */ |
diff = (unsigned int) ret; |
diff |= peer_pmslen ^ 48; |
diff |= peer_pms[0] ^ ver[0]; |
diff |= peer_pms[1] ^ ver[1]; |
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ |
/* MSVC has a warning about unary minus on unsigned, but this is |
* well-defined and precisely what we want to do here */ |
#if defined(_MSC_VER) |
#pragma warning( push ) |
#pragma warning( disable : 4146 ) |
#endif |
mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); |
#if defined(_MSC_VER) |
#pragma warning( pop ) |
#endif |
/* |
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding |
* must not cause the connection to end immediately; instead, send a |
* bad_record_mac later in the handshake. |
* To protect against timing-based variants of the attack, we must |
* not have any branch that depends on whether the decryption was |
* successful. In particular, always generate the fake premaster secret, |
* regardless of whether it will ultimately influence the output or not. |
*/ |
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); |
if( ret != 0 ) |
{ |
/* It's ok to abort on an RNG failure, since this does not reveal |
* anything about the RSA decryption. */ |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
if( diff != 0 ) |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
#endif |
if( sizeof( ssl->handshake->premaster ) < pms_offset || |
sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
ssl->handshake->pmslen = 48; |
/* Set pms to either the true or the fake PMS, without |
* data-dependent branches. */ |
for( i = 0; i < ssl->handshake->pmslen; i++ ) |
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, |
const unsigned char *end ) |
{ |
int ret = 0; |
size_t n; |
if( ssl->conf->f_psk == NULL && |
( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || |
ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); |
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); |
} |
/* |
* Receive client pre-shared key identity name |
*/ |
if( end - *p < 2 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
n = ( (*p)[0] << 8 ) | (*p)[1]; |
*p += 2; |
if( n < 1 || n > 65535 || n > (size_t) ( end - *p ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
if( ssl->conf->f_psk != NULL ) |
{ |
if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) |
ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; |
} |
else |
{ |
/* Identity is not a big secret since clients send it in the clear, |
* but treat it carefully anyway, just in case */ |
if( n != ssl->conf->psk_identity_len || |
mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) |
{ |
ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; |
} |
} |
if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) |
{ |
MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); |
return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); |
} |
*p += n; |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ |
static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info; |
unsigned char *p, *end; |
ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ |
( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) |
if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && |
( ssl->handshake->async_in_progress != 0 ) ) |
{ |
/* We've already read a record and there is an asynchronous |
* operation in progress to decrypt it. So skip reading the |
* record. */ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); |
} |
else |
#endif |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); |
end = ssl->in_msg + ssl->in_hslen; |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) |
{ |
if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); |
return( ret ); |
} |
if( p != end ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, |
ssl->handshake->premaster, |
MBEDTLS_PREMASTER_SIZE, |
&ssl->handshake->pmslen, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); |
} |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) |
{ |
if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, |
p, end - p) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); |
} |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_QP ); |
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, |
&ssl->handshake->pmslen, |
ssl->handshake->premaster, |
MBEDTLS_MPI_MAX_SIZE, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); |
} |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_Z ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || |
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) |
{ |
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); |
return( ret ); |
} |
if( p != end ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, |
ciphersuite_info->key_exchange ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) |
{ |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
if ( ssl->handshake->async_in_progress != 0 ) |
{ |
/* There is an asynchronous operation in progress to |
* decrypt the encrypted premaster secret, so skip |
* directly to resuming this operation. */ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); |
/* Update p to skip the PSK identity. ssl_parse_encrypted_pms |
* won't actually use it, but maintain p anyway for robustness. */ |
p += ssl->conf->psk_identity_len + 2; |
} |
else |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); |
return( ret ); |
} |
if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, |
ciphersuite_info->key_exchange ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) |
{ |
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); |
return( ret ); |
} |
if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); |
return( ret ); |
} |
if( p != end ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); |
} |
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, |
ciphersuite_info->key_exchange ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) |
{ |
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, |
p, end - p ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); |
} |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_QP ); |
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, |
ciphersuite_info->key_exchange ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) |
{ |
if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, |
p, end - p ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); |
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); |
} |
ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, |
ssl->handshake->premaster, 32, &ssl->handshake->pmslen, |
ssl->conf->f_rng, ssl->conf->p_rng ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); |
return( ret ); |
} |
ssl->state++; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); |
return( 0 ); |
} |
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) |
{ |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); |
ssl->state++; |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#else |
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
size_t i, sig_len; |
unsigned char hash[48]; |
unsigned char *hash_start = hash; |
size_t hashlen; |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
mbedtls_pk_type_t pk_alg; |
#endif |
mbedtls_md_type_t md_alg; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || |
ssl->session_negotiate->peer_cert == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); |
ssl->state++; |
return( 0 ); |
} |
/* Read the message without adding it to the checksum */ |
ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ ); |
if( 0 != ret ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret ); |
return( ret ); |
} |
ssl->state++; |
/* Process the message contents */ |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || |
ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); |
} |
i = mbedtls_ssl_hs_hdr_len( ssl ); |
/* |
* struct { |
* SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only |
* opaque signature<0..2^16-1>; |
* } DigitallySigned; |
*/ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
md_alg = MBEDTLS_MD_NONE; |
hashlen = 36; |
/* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ |
if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, |
MBEDTLS_PK_ECDSA ) ) |
{ |
hash_start += 16; |
hashlen -= 16; |
md_alg = MBEDTLS_MD_SHA1; |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || |
MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
if( i + 2 > ssl->in_hslen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); |
} |
/* |
* Hash |
*/ |
md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); |
if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" |
" for verify message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); |
} |
#if !defined(MBEDTLS_MD_SHA1) |
if( MBEDTLS_MD_SHA1 == md_alg ) |
hash_start += 16; |
#endif |
/* Info from md_alg will be used instead */ |
hashlen = 0; |
i++; |
/* |
* Signature |
*/ |
if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) |
== MBEDTLS_PK_NONE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" |
" for verify message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); |
} |
/* |
* Check the certificate's key type matches the signature alg |
*/ |
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); |
} |
i++; |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
if( i + 2 > ssl->in_hslen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); |
} |
sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; |
i += 2; |
if( i + sig_len != ssl->in_hslen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); |
} |
/* Calculate hash and verify signature */ |
ssl->handshake->calc_verify( ssl, hash ); |
if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, |
md_alg, hash_start, hashlen, |
ssl->in_msg + i, sig_len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); |
return( ret ); |
} |
mbedtls_ssl_update_handshake_status( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); |
return( ret ); |
} |
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && |
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
size_t tlen; |
uint32_t lifetime; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; |
/* |
* struct { |
* uint32 ticket_lifetime_hint; |
* opaque ticket<0..2^16-1>; |
* } NewSessionTicket; |
* |
* 4 . 7 ticket_lifetime_hint (0 = unspecified) |
* 8 . 9 ticket_len (n) |
* 10 . 9+n ticket content |
*/ |
if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, |
ssl->session_negotiate, |
ssl->out_msg + 10, |
ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, |
&tlen, &lifetime ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); |
tlen = 0; |
} |
ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; |
ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; |
ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; |
ssl->out_msg[7] = ( lifetime ) & 0xFF; |
ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); |
ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); |
ssl->out_msglen = 10 + tlen; |
/* |
* Morally equivalent to updating ssl->state, but NewSessionTicket and |
* ChangeCipherSpec share the same state. |
*/ |
ssl->handshake->new_session_ticket = 0; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
/* |
* SSL handshake -- server side -- single step |
*/ |
int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) |
{ |
int ret = 0; |
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); |
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
return( ret ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) |
{ |
if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
switch( ssl->state ) |
{ |
case MBEDTLS_SSL_HELLO_REQUEST: |
ssl->state = MBEDTLS_SSL_CLIENT_HELLO; |
break; |
/* |
* <== ClientHello |
*/ |
case MBEDTLS_SSL_CLIENT_HELLO: |
ret = ssl_parse_client_hello( ssl ); |
break; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: |
return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); |
#endif |
/* |
* ==> ServerHello |
* Certificate |
* ( ServerKeyExchange ) |
* ( CertificateRequest ) |
* ServerHelloDone |
*/ |
case MBEDTLS_SSL_SERVER_HELLO: |
ret = ssl_write_server_hello( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_CERTIFICATE: |
ret = mbedtls_ssl_write_certificate( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: |
ret = ssl_write_server_key_exchange( ssl ); |
break; |
case MBEDTLS_SSL_CERTIFICATE_REQUEST: |
ret = ssl_write_certificate_request( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_HELLO_DONE: |
ret = ssl_write_server_hello_done( ssl ); |
break; |
/* |
* <== ( Certificate/Alert ) |
* ClientKeyExchange |
* ( CertificateVerify ) |
* ChangeCipherSpec |
* Finished |
*/ |
case MBEDTLS_SSL_CLIENT_CERTIFICATE: |
ret = mbedtls_ssl_parse_certificate( ssl ); |
break; |
case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: |
ret = ssl_parse_client_key_exchange( ssl ); |
break; |
case MBEDTLS_SSL_CERTIFICATE_VERIFY: |
ret = ssl_parse_certificate_verify( ssl ); |
break; |
case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: |
ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); |
break; |
case MBEDTLS_SSL_CLIENT_FINISHED: |
ret = mbedtls_ssl_parse_finished( ssl ); |
break; |
/* |
* ==> ( NewSessionTicket ) |
* ChangeCipherSpec |
* Finished |
*/ |
case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
if( ssl->handshake->new_session_ticket != 0 ) |
ret = ssl_write_new_session_ticket( ssl ); |
else |
#endif |
ret = mbedtls_ssl_write_change_cipher_spec( ssl ); |
break; |
case MBEDTLS_SSL_SERVER_FINISHED: |
ret = mbedtls_ssl_write_finished( ssl ); |
break; |
case MBEDTLS_SSL_FLUSH_BUFFERS: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); |
ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; |
break; |
case MBEDTLS_SSL_HANDSHAKE_WRAPUP: |
mbedtls_ssl_handshake_wrapup( ssl ); |
break; |
default: |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_SRV_C */ |
/programs/develop/libraries/kos_mbedtls/library/ssl_ticket.c |
---|
0,0 → 1,487 |
/* |
* TLS server tickets callbacks implementation |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SSL_TICKET_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/ssl_ticket.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
/* |
* Initialze context |
*/ |
void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_init( &ctx->mutex ); |
#endif |
} |
#define MAX_KEY_BYTES 32 /* 256 bits */ |
/* |
* Generate/update a key |
*/ |
static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, |
unsigned char index ) |
{ |
int ret; |
unsigned char buf[MAX_KEY_BYTES]; |
mbedtls_ssl_ticket_key *key = ctx->keys + index; |
#if defined(MBEDTLS_HAVE_TIME) |
key->generation_time = (uint32_t) mbedtls_time( NULL ); |
#endif |
if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) |
return( ret ); |
if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) |
return( ret ); |
/* With GCM and CCM, same context can encrypt & decrypt */ |
ret = mbedtls_cipher_setkey( &key->ctx, buf, |
mbedtls_cipher_get_key_bitlen( &key->ctx ), |
MBEDTLS_ENCRYPT ); |
mbedtls_platform_zeroize( buf, sizeof( buf ) ); |
return( ret ); |
} |
/* |
* Rotate/generate keys if necessary |
*/ |
static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) |
{ |
#if !defined(MBEDTLS_HAVE_TIME) |
((void) ctx); |
#else |
if( ctx->ticket_lifetime != 0 ) |
{ |
uint32_t current_time = (uint32_t) mbedtls_time( NULL ); |
uint32_t key_time = ctx->keys[ctx->active].generation_time; |
if( current_time >= key_time && |
current_time - key_time < ctx->ticket_lifetime ) |
{ |
return( 0 ); |
} |
ctx->active = 1 - ctx->active; |
return( ssl_ticket_gen_key( ctx, ctx->active ) ); |
} |
else |
#endif /* MBEDTLS_HAVE_TIME */ |
return( 0 ); |
} |
/* |
* Setup context for actual use |
*/ |
int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, |
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
mbedtls_cipher_type_t cipher, |
uint32_t lifetime ) |
{ |
int ret; |
const mbedtls_cipher_info_t *cipher_info; |
ctx->f_rng = f_rng; |
ctx->p_rng = p_rng; |
ctx->ticket_lifetime = lifetime; |
cipher_info = mbedtls_cipher_info_from_type( cipher); |
if( cipher_info == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( cipher_info->mode != MBEDTLS_MODE_GCM && |
cipher_info->mode != MBEDTLS_MODE_CCM ) |
{ |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 || |
( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || |
( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
/* |
* Serialize a session in the following format: |
* 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) |
* n . n+2 peer_cert length = m (0 if no certificate) |
* n+3 . n+2+m peer cert ASN.1 |
*/ |
static int ssl_save_session( const mbedtls_ssl_session *session, |
unsigned char *buf, size_t buf_len, |
size_t *olen ) |
{ |
unsigned char *p = buf; |
size_t left = buf_len; |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
size_t cert_len; |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
if( left < sizeof( mbedtls_ssl_session ) ) |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
memcpy( p, session, sizeof( mbedtls_ssl_session ) ); |
p += sizeof( mbedtls_ssl_session ); |
left -= sizeof( mbedtls_ssl_session ); |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
if( session->peer_cert == NULL ) |
cert_len = 0; |
else |
cert_len = session->peer_cert->raw.len; |
if( left < 3 + cert_len ) |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
*p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); |
*p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); |
*p++ = (unsigned char)( ( cert_len ) & 0xFF ); |
if( session->peer_cert != NULL ) |
memcpy( p, session->peer_cert->raw.p, cert_len ); |
p += cert_len; |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
*olen = p - buf; |
return( 0 ); |
} |
/* |
* Unserialise session, see ssl_save_session() |
*/ |
static int ssl_load_session( mbedtls_ssl_session *session, |
const unsigned char *buf, size_t len ) |
{ |
const unsigned char *p = buf; |
const unsigned char * const end = buf + len; |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
size_t cert_len; |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
memcpy( session, p, sizeof( mbedtls_ssl_session ) ); |
p += sizeof( mbedtls_ssl_session ); |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
if( 3 > (size_t)( end - p ) ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; |
p += 3; |
if( cert_len == 0 ) |
{ |
session->peer_cert = NULL; |
} |
else |
{ |
int ret; |
if( cert_len > (size_t)( end - p ) ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); |
if( session->peer_cert == NULL ) |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
mbedtls_x509_crt_init( session->peer_cert ); |
if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, |
p, cert_len ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( session->peer_cert ); |
mbedtls_free( session->peer_cert ); |
session->peer_cert = NULL; |
return( ret ); |
} |
p += cert_len; |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
if( p != end ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
return( 0 ); |
} |
/* |
* Create session ticket, with the following structure: |
* |
* struct { |
* opaque key_name[4]; |
* opaque iv[12]; |
* opaque encrypted_state<0..2^16-1>; |
* opaque tag[16]; |
* } ticket; |
* |
* The key_name, iv, and length of encrypted_state are the additional |
* authenticated data. |
*/ |
int mbedtls_ssl_ticket_write( void *p_ticket, |
const mbedtls_ssl_session *session, |
unsigned char *start, |
const unsigned char *end, |
size_t *tlen, |
uint32_t *ticket_lifetime ) |
{ |
int ret; |
mbedtls_ssl_ticket_context *ctx = p_ticket; |
mbedtls_ssl_ticket_key *key; |
unsigned char *key_name = start; |
unsigned char *iv = start + 4; |
unsigned char *state_len_bytes = iv + 12; |
unsigned char *state = state_len_bytes + 2; |
unsigned char *tag; |
size_t clear_len, ciph_len; |
*tlen = 0; |
if( ctx == NULL || ctx->f_rng == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
/* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, |
* in addition to session itself, that will be checked when writing it. */ |
if( end - start < 4 + 12 + 2 + 16 ) |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) |
goto cleanup; |
key = &ctx->keys[ctx->active]; |
*ticket_lifetime = ctx->ticket_lifetime; |
memcpy( key_name, key->name, 4 ); |
if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 ) |
goto cleanup; |
/* Dump session state */ |
if( ( ret = ssl_save_session( session, |
state, end - state, &clear_len ) ) != 0 || |
(unsigned long) clear_len > 65535 ) |
{ |
goto cleanup; |
} |
state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; |
state_len_bytes[1] = ( clear_len ) & 0xff; |
/* Encrypt and authenticate */ |
tag = state + clear_len; |
if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, |
iv, 12, key_name, 4 + 12 + 2, |
state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 ) |
{ |
goto cleanup; |
} |
if( ciph_len != clear_len ) |
{ |
ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; |
goto cleanup; |
} |
*tlen = 4 + 12 + 2 + 16 + ciph_len; |
cleanup: |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
/* |
* Select key based on name |
*/ |
static mbedtls_ssl_ticket_key *ssl_ticket_select_key( |
mbedtls_ssl_ticket_context *ctx, |
const unsigned char name[4] ) |
{ |
unsigned char i; |
for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) |
if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) |
return( &ctx->keys[i] ); |
return( NULL ); |
} |
/* |
* Load session ticket (see mbedtls_ssl_ticket_write for structure) |
*/ |
int mbedtls_ssl_ticket_parse( void *p_ticket, |
mbedtls_ssl_session *session, |
unsigned char *buf, |
size_t len ) |
{ |
int ret; |
mbedtls_ssl_ticket_context *ctx = p_ticket; |
mbedtls_ssl_ticket_key *key; |
unsigned char *key_name = buf; |
unsigned char *iv = buf + 4; |
unsigned char *enc_len_p = iv + 12; |
unsigned char *ticket = enc_len_p + 2; |
unsigned char *tag; |
size_t enc_len, clear_len; |
if( ctx == NULL || ctx->f_rng == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
/* See mbedtls_ssl_ticket_write() */ |
if( len < 4 + 12 + 2 + 16 ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) |
return( ret ); |
#endif |
if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) |
goto cleanup; |
enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; |
tag = ticket + enc_len; |
if( len != 4 + 12 + 2 + enc_len + 16 ) |
{ |
ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; |
goto cleanup; |
} |
/* Select key */ |
if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) |
{ |
/* We can't know for sure but this is a likely option unless we're |
* under attack - this is only informative anyway */ |
ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; |
goto cleanup; |
} |
/* Decrypt and authenticate */ |
if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12, |
key_name, 4 + 12 + 2, ticket, enc_len, |
ticket, &clear_len, tag, 16 ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) |
ret = MBEDTLS_ERR_SSL_INVALID_MAC; |
goto cleanup; |
} |
if( clear_len != enc_len ) |
{ |
ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; |
goto cleanup; |
} |
/* Actually load session */ |
if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 ) |
goto cleanup; |
#if defined(MBEDTLS_HAVE_TIME) |
{ |
/* Check for expiration */ |
mbedtls_time_t current_time = mbedtls_time( NULL ); |
if( current_time < session->start || |
(uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) |
{ |
ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; |
goto cleanup; |
} |
} |
#endif |
cleanup: |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
#endif |
return( ret ); |
} |
/* |
* Free context |
*/ |
void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) |
{ |
mbedtls_cipher_free( &ctx->keys[0].ctx ); |
mbedtls_cipher_free( &ctx->keys[1].ctx ); |
#if defined(MBEDTLS_THREADING_C) |
mbedtls_mutex_free( &ctx->mutex ); |
#endif |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); |
} |
#endif /* MBEDTLS_SSL_TICKET_C */ |
/programs/develop/libraries/kos_mbedtls/library/ssl_tls.c |
---|
0,0 → 1,9807 |
/* |
* SSLv3/TLSv1 shared functions |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The SSL 3.0 specification was drafted by Netscape in 1996, |
* and became an IETF standard in 1999. |
* |
* http://wp.netscape.com/eng/ssl3/ |
* http://www.ietf.org/rfc/rfc2246.txt |
* http://www.ietf.org/rfc/rfc4346.txt |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SSL_TLS_C) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#define mbedtls_calloc calloc |
#define mbedtls_free free |
#endif |
#include "mbedtls/debug.h" |
#include "mbedtls/ssl.h" |
#include "mbedtls/ssl_internal.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
#include "mbedtls/oid.h" |
#endif |
static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); |
static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); |
/* Length of the "epoch" field in the record header */ |
static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
return( 2 ); |
#else |
((void) ssl); |
#endif |
return( 0 ); |
} |
/* |
* Start a timer. |
* Passing millisecs = 0 cancels a running timer. |
*/ |
static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) |
{ |
if( ssl->f_set_timer == NULL ) |
return; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); |
ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); |
} |
/* |
* Return -1 is timer is expired, 0 if it isn't. |
*/ |
static int ssl_check_timer( mbedtls_ssl_context *ssl ) |
{ |
if( ssl->f_get_timer == NULL ) |
return( 0 ); |
if( ssl->f_get_timer( ssl->p_timer ) == 2 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); |
return( -1 ); |
} |
return( 0 ); |
} |
static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, |
mbedtls_ssl_transform *transform ); |
static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, |
mbedtls_ssl_transform *transform ); |
#define SSL_DONT_FORCE_FLUSH 0 |
#define SSL_FORCE_FLUSH 1 |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
/* Forward declarations for functions related to message buffering. */ |
static void ssl_buffering_free( mbedtls_ssl_context *ssl ); |
static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, |
uint8_t slot ); |
static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); |
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); |
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); |
static int ssl_buffer_message( mbedtls_ssl_context *ssl ); |
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ); |
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); |
static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); |
static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) |
{ |
size_t mtu = ssl_get_current_mtu( ssl ); |
if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN ) |
return( mtu ); |
return( MBEDTLS_SSL_OUT_BUFFER_LEN ); |
} |
static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) |
{ |
size_t const bytes_written = ssl->out_left; |
size_t const mtu = ssl_get_maximum_datagram_size( ssl ); |
/* Double-check that the write-index hasn't gone |
* past what we can transmit in a single datagram. */ |
if( bytes_written > mtu ) |
{ |
/* Should never happen... */ |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
return( (int) ( mtu - bytes_written ) ); |
} |
static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) |
{ |
int ret; |
size_t remaining, expansion; |
size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); |
if( max_len > mfl ) |
max_len = mfl; |
/* By the standard (RFC 6066 Sect. 4), the MFL extension |
* only limits the maximum record payload size, so in theory |
* we would be allowed to pack multiple records of payload size |
* MFL into a single datagram. However, this would mean that there's |
* no way to explicitly communicate MTU restrictions to the peer. |
* |
* The following reduction of max_len makes sure that we never |
* write datagrams larger than MFL + Record Expansion Overhead. |
*/ |
if( max_len <= ssl->out_left ) |
return( 0 ); |
max_len -= ssl->out_left; |
#endif |
ret = ssl_get_remaining_space_in_datagram( ssl ); |
if( ret < 0 ) |
return( ret ); |
remaining = (size_t) ret; |
ret = mbedtls_ssl_get_record_expansion( ssl ); |
if( ret < 0 ) |
return( ret ); |
expansion = (size_t) ret; |
if( remaining <= expansion ) |
return( 0 ); |
remaining -= expansion; |
if( remaining >= max_len ) |
remaining = max_len; |
return( (int) remaining ); |
} |
/* |
* Double the retransmit timeout value, within the allowed range, |
* returning -1 if the maximum value has already been reached. |
*/ |
static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) |
{ |
uint32_t new_timeout; |
if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) |
return( -1 ); |
/* Implement the final paragraph of RFC 6347 section 4.1.1.1 |
* in the following way: after the initial transmission and a first |
* retransmission, back off to a temporary estimated MTU of 508 bytes. |
* This value is guaranteed to be deliverable (if not guaranteed to be |
* delivered) of any compliant IPv4 (and IPv6) network, and should work |
* on most non-IP stacks too. */ |
if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) |
{ |
ssl->handshake->mtu = 508; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); |
} |
new_timeout = 2 * ssl->handshake->retransmit_timeout; |
/* Avoid arithmetic overflow and range overflow */ |
if( new_timeout < ssl->handshake->retransmit_timeout || |
new_timeout > ssl->conf->hs_timeout_max ) |
{ |
new_timeout = ssl->conf->hs_timeout_max; |
} |
ssl->handshake->retransmit_timeout = new_timeout; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", |
ssl->handshake->retransmit_timeout ) ); |
return( 0 ); |
} |
static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) |
{ |
ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", |
ssl->handshake->retransmit_timeout ) ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
/* |
* Convert max_fragment_length codes to length. |
* RFC 6066 says: |
* enum{ |
* 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) |
* } MaxFragmentLength; |
* and we add 0 -> extension unused |
*/ |
static unsigned int ssl_mfl_code_to_length( int mfl ) |
{ |
switch( mfl ) |
{ |
case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: |
return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); |
case MBEDTLS_SSL_MAX_FRAG_LEN_512: |
return 512; |
case MBEDTLS_SSL_MAX_FRAG_LEN_1024: |
return 1024; |
case MBEDTLS_SSL_MAX_FRAG_LEN_2048: |
return 2048; |
case MBEDTLS_SSL_MAX_FRAG_LEN_4096: |
return 4096; |
default: |
return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); |
} |
} |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_CLI_C) |
static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ) |
{ |
mbedtls_ssl_session_free( dst ); |
memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
if( src->peer_cert != NULL ) |
{ |
int ret; |
dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); |
if( dst->peer_cert == NULL ) |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
mbedtls_x509_crt_init( dst->peer_cert ); |
if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, |
src->peer_cert->raw.len ) ) != 0 ) |
{ |
mbedtls_free( dst->peer_cert ); |
dst->peer_cert = NULL; |
return( ret ); |
} |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) |
if( src->ticket != NULL ) |
{ |
dst->ticket = mbedtls_calloc( 1, src->ticket_len ); |
if( dst->ticket == NULL ) |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
memcpy( dst->ticket, src->ticket, src->ticket_len ); |
} |
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_CLI_C */ |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, |
const unsigned char *key_enc, const unsigned char *key_dec, |
size_t keylen, |
const unsigned char *iv_enc, const unsigned char *iv_dec, |
size_t ivlen, |
const unsigned char *mac_enc, const unsigned char *mac_dec, |
size_t maclen ) = NULL; |
int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; |
int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; |
int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; |
int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; |
int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; |
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ |
/* |
* Key material generation |
*/ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
static int ssl3_prf( const unsigned char *secret, size_t slen, |
const char *label, |
const unsigned char *random, size_t rlen, |
unsigned char *dstbuf, size_t dlen ) |
{ |
int ret = 0; |
size_t i; |
mbedtls_md5_context md5; |
mbedtls_sha1_context sha1; |
unsigned char padding[16]; |
unsigned char sha1sum[20]; |
((void)label); |
mbedtls_md5_init( &md5 ); |
mbedtls_sha1_init( &sha1 ); |
/* |
* SSLv3: |
* block = |
* MD5( secret + SHA1( 'A' + secret + random ) ) + |
* MD5( secret + SHA1( 'BB' + secret + random ) ) + |
* MD5( secret + SHA1( 'CCC' + secret + random ) ) + |
* ... |
*/ |
for( i = 0; i < dlen / 16; i++ ) |
{ |
memset( padding, (unsigned char) ('A' + i), 1 + i ); |
if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 ) |
goto exit; |
if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 ) |
goto exit; |
} |
exit: |
mbedtls_md5_free( &md5 ); |
mbedtls_sha1_free( &sha1 ); |
mbedtls_platform_zeroize( padding, sizeof( padding ) ); |
mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) |
static int tls1_prf( const unsigned char *secret, size_t slen, |
const char *label, |
const unsigned char *random, size_t rlen, |
unsigned char *dstbuf, size_t dlen ) |
{ |
size_t nb, hs; |
size_t i, j, k; |
const unsigned char *S1, *S2; |
unsigned char tmp[128]; |
unsigned char h_i[20]; |
const mbedtls_md_info_t *md_info; |
mbedtls_md_context_t md_ctx; |
int ret; |
mbedtls_md_init( &md_ctx ); |
if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
hs = ( slen + 1 ) / 2; |
S1 = secret; |
S2 = secret + slen - hs; |
nb = strlen( label ); |
memcpy( tmp + 20, label, nb ); |
memcpy( tmp + 20 + nb, random, rlen ); |
nb += rlen; |
/* |
* First compute P_md5(secret,label+random)[0..dlen] |
*/ |
if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) |
return( ret ); |
mbedtls_md_hmac_starts( &md_ctx, S1, hs ); |
mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); |
mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); |
for( i = 0; i < dlen; i += 16 ) |
{ |
mbedtls_md_hmac_reset ( &md_ctx ); |
mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); |
mbedtls_md_hmac_finish( &md_ctx, h_i ); |
mbedtls_md_hmac_reset ( &md_ctx ); |
mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); |
mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); |
k = ( i + 16 > dlen ) ? dlen % 16 : 16; |
for( j = 0; j < k; j++ ) |
dstbuf[i + j] = h_i[j]; |
} |
mbedtls_md_free( &md_ctx ); |
/* |
* XOR out with P_sha1(secret,label+random)[0..dlen] |
*/ |
if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) |
return( ret ); |
mbedtls_md_hmac_starts( &md_ctx, S2, hs ); |
mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); |
mbedtls_md_hmac_finish( &md_ctx, tmp ); |
for( i = 0; i < dlen; i += 20 ) |
{ |
mbedtls_md_hmac_reset ( &md_ctx ); |
mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); |
mbedtls_md_hmac_finish( &md_ctx, h_i ); |
mbedtls_md_hmac_reset ( &md_ctx ); |
mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); |
mbedtls_md_hmac_finish( &md_ctx, tmp ); |
k = ( i + 20 > dlen ) ? dlen % 20 : 20; |
for( j = 0; j < k; j++ ) |
dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); |
} |
mbedtls_md_free( &md_ctx ); |
mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); |
mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
static int tls_prf_generic( mbedtls_md_type_t md_type, |
const unsigned char *secret, size_t slen, |
const char *label, |
const unsigned char *random, size_t rlen, |
unsigned char *dstbuf, size_t dlen ) |
{ |
size_t nb; |
size_t i, j, k, md_len; |
unsigned char tmp[128]; |
unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; |
const mbedtls_md_info_t *md_info; |
mbedtls_md_context_t md_ctx; |
int ret; |
mbedtls_md_init( &md_ctx ); |
if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
md_len = mbedtls_md_get_size( md_info ); |
if( sizeof( tmp ) < md_len + strlen( label ) + rlen ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
nb = strlen( label ); |
memcpy( tmp + md_len, label, nb ); |
memcpy( tmp + md_len + nb, random, rlen ); |
nb += rlen; |
/* |
* Compute P_<hash>(secret, label + random)[0..dlen] |
*/ |
if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) |
return( ret ); |
mbedtls_md_hmac_starts( &md_ctx, secret, slen ); |
mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); |
mbedtls_md_hmac_finish( &md_ctx, tmp ); |
for( i = 0; i < dlen; i += md_len ) |
{ |
mbedtls_md_hmac_reset ( &md_ctx ); |
mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); |
mbedtls_md_hmac_finish( &md_ctx, h_i ); |
mbedtls_md_hmac_reset ( &md_ctx ); |
mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); |
mbedtls_md_hmac_finish( &md_ctx, tmp ); |
k = ( i + md_len > dlen ) ? dlen % md_len : md_len; |
for( j = 0; j < k; j++ ) |
dstbuf[i + j] = h_i[j]; |
} |
mbedtls_md_free( &md_ctx ); |
mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); |
mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SHA256_C) |
static int tls_prf_sha256( const unsigned char *secret, size_t slen, |
const char *label, |
const unsigned char *random, size_t rlen, |
unsigned char *dstbuf, size_t dlen ) |
{ |
return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, |
label, random, rlen, dstbuf, dlen ) ); |
} |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
static int tls_prf_sha384( const unsigned char *secret, size_t slen, |
const char *label, |
const unsigned char *random, size_t rlen, |
unsigned char *dstbuf, size_t dlen ) |
{ |
return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, |
label, random, rlen, dstbuf, dlen ) ); |
} |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); |
static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) |
static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); |
static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); |
static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * ); |
static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); |
static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); |
static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) |
{ |
int ret = 0; |
unsigned char tmp[64]; |
unsigned char keyblk[256]; |
unsigned char *key1; |
unsigned char *key2; |
unsigned char *mac_enc; |
unsigned char *mac_dec; |
size_t mac_key_len; |
size_t iv_copy_len; |
const mbedtls_cipher_info_t *cipher_info; |
const mbedtls_md_info_t *md_info; |
mbedtls_ssl_session *session = ssl->session_negotiate; |
mbedtls_ssl_transform *transform = ssl->transform_negotiate; |
mbedtls_ssl_handshake_params *handshake = ssl->handshake; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); |
cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher ); |
if( cipher_info == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", |
transform->ciphersuite_info->cipher ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac ); |
if( md_info == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", |
transform->ciphersuite_info->mac ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
/* |
* Set appropriate PRF function and other SSL / TLS / TLS1.2 functions |
*/ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
handshake->tls_prf = ssl3_prf; |
handshake->calc_verify = ssl_calc_verify_ssl; |
handshake->calc_finished = ssl_calc_finished_ssl; |
} |
else |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
handshake->tls_prf = tls1_prf; |
handshake->calc_verify = ssl_calc_verify_tls; |
handshake->calc_finished = ssl_calc_finished_tls; |
} |
else |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA512_C) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && |
transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) |
{ |
handshake->tls_prf = tls_prf_sha384; |
handshake->calc_verify = ssl_calc_verify_tls_sha384; |
handshake->calc_finished = ssl_calc_finished_tls_sha384; |
} |
else |
#endif |
#if defined(MBEDTLS_SHA256_C) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
handshake->tls_prf = tls_prf_sha256; |
handshake->calc_verify = ssl_calc_verify_tls_sha256; |
handshake->calc_finished = ssl_calc_finished_tls_sha256; |
} |
else |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* |
* SSLv3: |
* master = |
* MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + |
* MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + |
* MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) |
* |
* TLSv1+: |
* master = PRF( premaster, "master secret", randbytes )[0..47] |
*/ |
if( handshake->resume == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, |
handshake->pmslen ); |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) |
{ |
unsigned char session_hash[48]; |
size_t hash_len; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); |
ssl->handshake->calc_verify( ssl, session_hash ); |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
#if defined(MBEDTLS_SHA512_C) |
if( ssl->transform_negotiate->ciphersuite_info->mac == |
MBEDTLS_MD_SHA384 ) |
{ |
hash_len = 48; |
} |
else |
#endif |
hash_len = 32; |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
hash_len = 36; |
MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); |
ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, |
"extended master secret", |
session_hash, hash_len, |
session->master, 48 ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); |
return( ret ); |
} |
} |
else |
#endif |
ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, |
"master secret", |
handshake->randbytes, 64, |
session->master, 48 ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); |
return( ret ); |
} |
mbedtls_platform_zeroize( handshake->premaster, |
sizeof(handshake->premaster) ); |
} |
else |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); |
/* |
* Swap the client and server random values. |
*/ |
memcpy( tmp, handshake->randbytes, 64 ); |
memcpy( handshake->randbytes, tmp + 32, 32 ); |
memcpy( handshake->randbytes + 32, tmp, 32 ); |
mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); |
/* |
* SSLv3: |
* key block = |
* MD5( master + SHA1( 'A' + master + randbytes ) ) + |
* MD5( master + SHA1( 'BB' + master + randbytes ) ) + |
* MD5( master + SHA1( 'CCC' + master + randbytes ) ) + |
* MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + |
* ... |
* |
* TLSv1: |
* key block = PRF( master, "key expansion", randbytes ) |
*/ |
ret = handshake->tls_prf( session->master, 48, "key expansion", |
handshake->randbytes, 64, keyblk, 256 ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", |
mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); |
mbedtls_platform_zeroize( handshake->randbytes, |
sizeof( handshake->randbytes ) ); |
/* |
* Determine the appropriate key, IV and MAC length. |
*/ |
transform->keylen = cipher_info->key_bitlen / 8; |
if( cipher_info->mode == MBEDTLS_MODE_GCM || |
cipher_info->mode == MBEDTLS_MODE_CCM || |
cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) |
{ |
size_t taglen, explicit_ivlen; |
transform->maclen = 0; |
mac_key_len = 0; |
/* All modes haves 96-bit IVs; |
* GCM and CCM has 4 implicit and 8 explicit bytes |
* ChachaPoly has all 12 bytes implicit |
*/ |
transform->ivlen = 12; |
if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) |
transform->fixed_ivlen = 12; |
else |
transform->fixed_ivlen = 4; |
/* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */ |
taglen = transform->ciphersuite_info->flags & |
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; |
/* Minimum length of encrypted record */ |
explicit_ivlen = transform->ivlen - transform->fixed_ivlen; |
transform->minlen = explicit_ivlen + taglen; |
} |
else |
{ |
/* Initialize HMAC contexts */ |
if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || |
( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); |
return( ret ); |
} |
/* Get MAC length */ |
mac_key_len = mbedtls_md_get_size( md_info ); |
transform->maclen = mac_key_len; |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
/* |
* If HMAC is to be truncated, we shall keep the leftmost bytes, |
* (rfc 6066 page 13 or rfc 2104 section 4), |
* so we only need to adjust the length here. |
*/ |
if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) |
{ |
transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) |
/* Fall back to old, non-compliant version of the truncated |
* HMAC implementation which also truncates the key |
* (Mbed TLS versions from 1.3 to 2.6.0) */ |
mac_key_len = transform->maclen; |
#endif |
} |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
/* IV length */ |
transform->ivlen = cipher_info->iv_size; |
/* Minimum length */ |
if( cipher_info->mode == MBEDTLS_MODE_STREAM ) |
transform->minlen = transform->maclen; |
else |
{ |
/* |
* GenericBlockCipher: |
* 1. if EtM is in use: one block plus MAC |
* otherwise: * first multiple of blocklen greater than maclen |
* 2. IV except for SSL3 and TLS 1.0 |
*/ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) |
{ |
transform->minlen = transform->maclen |
+ cipher_info->block_size; |
} |
else |
#endif |
{ |
transform->minlen = transform->maclen |
+ cipher_info->block_size |
- transform->maclen % cipher_info->block_size; |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) |
; /* No need to adjust minlen */ |
else |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) |
{ |
transform->minlen += transform->ivlen; |
} |
else |
#endif |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", |
transform->keylen, transform->minlen, transform->ivlen, |
transform->maclen ) ); |
/* |
* Finally setup the cipher contexts, IVs and MAC secrets. |
*/ |
#if defined(MBEDTLS_SSL_CLI_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) |
{ |
key1 = keyblk + mac_key_len * 2; |
key2 = keyblk + mac_key_len * 2 + transform->keylen; |
mac_enc = keyblk; |
mac_dec = keyblk + mac_key_len; |
/* |
* This is not used in TLS v1.1. |
*/ |
iv_copy_len = ( transform->fixed_ivlen ) ? |
transform->fixed_ivlen : transform->ivlen; |
memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); |
memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, |
iv_copy_len ); |
} |
else |
#endif /* MBEDTLS_SSL_CLI_C */ |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
{ |
key1 = keyblk + mac_key_len * 2 + transform->keylen; |
key2 = keyblk + mac_key_len * 2; |
mac_enc = keyblk + mac_key_len; |
mac_dec = keyblk; |
/* |
* This is not used in TLS v1.1. |
*/ |
iv_copy_len = ( transform->fixed_ivlen ) ? |
transform->fixed_ivlen : transform->ivlen; |
memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); |
memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, |
iv_copy_len ); |
} |
else |
#endif /* MBEDTLS_SSL_SRV_C */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
if( mac_key_len > sizeof transform->mac_enc ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
memcpy( transform->mac_enc, mac_enc, mac_key_len ); |
memcpy( transform->mac_dec, mac_dec, mac_key_len ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) |
{ |
/* For HMAC-based ciphersuites, initialize the HMAC transforms. |
For AEAD-based ciphersuites, there is nothing to do here. */ |
if( mac_key_len != 0 ) |
{ |
mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); |
mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); |
} |
} |
else |
#endif |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_init != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); |
if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen, |
transform->iv_enc, transform->iv_dec, |
iv_copy_len, |
mac_enc, mac_dec, |
mac_key_len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); |
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); |
} |
} |
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ |
#if defined(MBEDTLS_SSL_EXPORT_KEYS) |
if( ssl->conf->f_export_keys != NULL ) |
{ |
ssl->conf->f_export_keys( ssl->conf->p_export_keys, |
session->master, keyblk, |
mac_key_len, transform->keylen, |
iv_copy_len ); |
} |
#endif |
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, |
cipher_info ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, |
cipher_info ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, |
cipher_info->key_bitlen, |
MBEDTLS_ENCRYPT ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, |
cipher_info->key_bitlen, |
MBEDTLS_DECRYPT ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
if( cipher_info->mode == MBEDTLS_MODE_CBC ) |
{ |
if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, |
MBEDTLS_PADDING_NONE ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); |
return( ret ); |
} |
if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, |
MBEDTLS_PADDING_NONE ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); |
return( ret ); |
} |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
// Initialize compression |
// |
if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) |
{ |
if( ssl->compress_buf == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); |
ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); |
if( ssl->compress_buf == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", |
MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); |
memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); |
memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); |
if( deflateInit( &transform->ctx_deflate, |
Z_DEFAULT_COMPRESSION ) != Z_OK || |
inflateInit( &transform->ctx_inflate ) != Z_OK ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); |
return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); |
} |
} |
#endif /* MBEDTLS_ZLIB_SUPPORT */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) |
{ |
mbedtls_md5_context md5; |
mbedtls_sha1_context sha1; |
unsigned char pad_1[48]; |
unsigned char pad_2[48]; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); |
mbedtls_md5_init( &md5 ); |
mbedtls_sha1_init( &sha1 ); |
mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); |
mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); |
memset( pad_1, 0x36, 48 ); |
memset( pad_2, 0x5C, 48 ); |
mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); |
mbedtls_md5_update_ret( &md5, pad_1, 48 ); |
mbedtls_md5_finish_ret( &md5, hash ); |
mbedtls_md5_starts_ret( &md5 ); |
mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); |
mbedtls_md5_update_ret( &md5, pad_2, 48 ); |
mbedtls_md5_update_ret( &md5, hash, 16 ); |
mbedtls_md5_finish_ret( &md5, hash ); |
mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); |
mbedtls_sha1_update_ret( &sha1, pad_1, 40 ); |
mbedtls_sha1_finish_ret( &sha1, hash + 16 ); |
mbedtls_sha1_starts_ret( &sha1 ); |
mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); |
mbedtls_sha1_update_ret( &sha1, pad_2, 40 ); |
mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); |
mbedtls_sha1_finish_ret( &sha1, hash + 16 ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); |
mbedtls_md5_free( &md5 ); |
mbedtls_sha1_free( &sha1 ); |
return; |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) |
void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) |
{ |
mbedtls_md5_context md5; |
mbedtls_sha1_context sha1; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); |
mbedtls_md5_init( &md5 ); |
mbedtls_sha1_init( &sha1 ); |
mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); |
mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); |
mbedtls_md5_finish_ret( &md5, hash ); |
mbedtls_sha1_finish_ret( &sha1, hash + 16 ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); |
mbedtls_md5_free( &md5 ); |
mbedtls_sha1_free( &sha1 ); |
return; |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) |
{ |
mbedtls_sha256_context sha256; |
mbedtls_sha256_init( &sha256 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); |
mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); |
mbedtls_sha256_finish_ret( &sha256, hash ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); |
mbedtls_sha256_free( &sha256 ); |
return; |
} |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] ) |
{ |
mbedtls_sha512_context sha512; |
mbedtls_sha512_init( &sha512 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); |
mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); |
mbedtls_sha512_finish_ret( &sha512, hash ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); |
mbedtls_sha512_free( &sha512 ); |
return; |
} |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) |
{ |
unsigned char *p = ssl->handshake->premaster; |
unsigned char *end = p + sizeof( ssl->handshake->premaster ); |
const unsigned char *psk = ssl->conf->psk; |
size_t psk_len = ssl->conf->psk_len; |
/* If the psk callback was called, use its result */ |
if( ssl->handshake->psk != NULL ) |
{ |
psk = ssl->handshake->psk; |
psk_len = ssl->handshake->psk_len; |
} |
/* |
* PMS = struct { |
* opaque other_secret<0..2^16-1>; |
* opaque psk<0..2^16-1>; |
* }; |
* with "other_secret" depending on the particular key exchange |
*/ |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) |
{ |
if( end - p < 2 ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
*(p++) = (unsigned char)( psk_len >> 8 ); |
*(p++) = (unsigned char)( psk_len ); |
if( end < p || (size_t)( end - p ) < psk_len ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
memset( p, 0, psk_len ); |
p += psk_len; |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) |
{ |
/* |
* other_secret already set by the ClientKeyExchange message, |
* and is 48 bytes long |
*/ |
if( end - p < 2 ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
*p++ = 0; |
*p++ = 48; |
p += 48; |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) |
{ |
int ret; |
size_t len; |
/* Write length only when we know the actual value */ |
if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, |
p + 2, end - ( p + 2 ), &len, |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); |
return( ret ); |
} |
*(p++) = (unsigned char)( len >> 8 ); |
*(p++) = (unsigned char)( len ); |
p += len; |
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) |
{ |
int ret; |
size_t zlen; |
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, |
p + 2, end - ( p + 2 ), |
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); |
return( ret ); |
} |
*(p++) = (unsigned char)( zlen >> 8 ); |
*(p++) = (unsigned char)( zlen ); |
p += zlen; |
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, |
MBEDTLS_DEBUG_ECDH_Z ); |
} |
else |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* opaque psk<0..2^16-1>; */ |
if( end - p < 2 ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
*(p++) = (unsigned char)( psk_len >> 8 ); |
*(p++) = (unsigned char)( psk_len ); |
if( end < p || (size_t)( end - p ) < psk_len ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
memcpy( p, psk, psk_len ); |
p += psk_len; |
ssl->handshake->pmslen = p - ssl->handshake->premaster; |
return( 0 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
/* |
* SSLv3.0 MAC functions |
*/ |
#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ |
static void ssl_mac( mbedtls_md_context_t *md_ctx, |
const unsigned char *secret, |
const unsigned char *buf, size_t len, |
const unsigned char *ctr, int type, |
unsigned char out[SSL_MAC_MAX_BYTES] ) |
{ |
unsigned char header[11]; |
unsigned char padding[48]; |
int padlen; |
int md_size = mbedtls_md_get_size( md_ctx->md_info ); |
int md_type = mbedtls_md_get_type( md_ctx->md_info ); |
/* Only MD5 and SHA-1 supported */ |
if( md_type == MBEDTLS_MD_MD5 ) |
padlen = 48; |
else |
padlen = 40; |
memcpy( header, ctr, 8 ); |
header[ 8] = (unsigned char) type; |
header[ 9] = (unsigned char)( len >> 8 ); |
header[10] = (unsigned char)( len ); |
memset( padding, 0x36, padlen ); |
mbedtls_md_starts( md_ctx ); |
mbedtls_md_update( md_ctx, secret, md_size ); |
mbedtls_md_update( md_ctx, padding, padlen ); |
mbedtls_md_update( md_ctx, header, 11 ); |
mbedtls_md_update( md_ctx, buf, len ); |
mbedtls_md_finish( md_ctx, out ); |
memset( padding, 0x5C, padlen ); |
mbedtls_md_starts( md_ctx ); |
mbedtls_md_update( md_ctx, secret, md_size ); |
mbedtls_md_update( md_ctx, padding, padlen ); |
mbedtls_md_update( md_ctx, out, md_size ); |
mbedtls_md_finish( md_ctx, out ); |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ |
( defined(MBEDTLS_CIPHER_MODE_CBC) && \ |
( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C)) ) |
#define SSL_SOME_MODES_USE_MAC |
#endif |
/* The function below is only used in the Lucky 13 counter-measure in |
* ssl_decrypt_buf(). These are the defines that guard the call site. */ |
#if defined(SSL_SOME_MODES_USE_MAC) && \ |
( defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) ) |
/* This function makes sure every byte in the memory region is accessed |
* (in ascending addresses order) */ |
static void ssl_read_memory( unsigned char *p, size_t len ) |
{ |
unsigned char acc = 0; |
volatile unsigned char force; |
for( ; len != 0; p++, len-- ) |
acc ^= *p; |
force = acc; |
(void) force; |
} |
#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */ |
/* |
* Encryption/decryption functions |
*/ |
static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_cipher_mode_t mode; |
int auth_done = 0; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); |
if( ssl->session_out == NULL || ssl->transform_out == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", |
ssl->out_msg, ssl->out_msglen ); |
/* |
* Add MAC before if needed |
*/ |
#if defined(SSL_SOME_MODES_USE_MAC) |
if( mode == MBEDTLS_MODE_STREAM || |
( mode == MBEDTLS_MODE_CBC |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
&& ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED |
#endif |
) ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
unsigned char mac[SSL_MAC_MAX_BYTES]; |
ssl_mac( &ssl->transform_out->md_ctx_enc, |
ssl->transform_out->mac_enc, |
ssl->out_msg, ssl->out_msglen, |
ssl->out_ctr, ssl->out_msgtype, |
mac ); |
memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); |
} |
else |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) |
{ |
unsigned char mac[MBEDTLS_SSL_MAC_ADD]; |
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); |
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); |
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); |
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, |
ssl->out_msg, ssl->out_msglen ); |
mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); |
mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); |
memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); |
} |
else |
#endif |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", |
ssl->out_msg + ssl->out_msglen, |
ssl->transform_out->maclen ); |
ssl->out_msglen += ssl->transform_out->maclen; |
auth_done++; |
} |
#endif /* AEAD not the only option */ |
/* |
* Encrypt |
*/ |
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) |
if( mode == MBEDTLS_MODE_STREAM ) |
{ |
int ret; |
size_t olen = 0; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " |
"including %d bytes of padding", |
ssl->out_msglen, 0 ) ); |
if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, |
ssl->transform_out->iv_enc, |
ssl->transform_out->ivlen, |
ssl->out_msg, ssl->out_msglen, |
ssl->out_msg, &olen ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); |
return( ret ); |
} |
if( ssl->out_msglen != olen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
else |
#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ |
#if defined(MBEDTLS_GCM_C) || \ |
defined(MBEDTLS_CCM_C) || \ |
defined(MBEDTLS_CHACHAPOLY_C) |
if( mode == MBEDTLS_MODE_GCM || |
mode == MBEDTLS_MODE_CCM || |
mode == MBEDTLS_MODE_CHACHAPOLY ) |
{ |
int ret; |
size_t enc_msglen, olen; |
unsigned char *enc_msg; |
unsigned char add_data[13]; |
unsigned char iv[12]; |
mbedtls_ssl_transform *transform = ssl->transform_out; |
unsigned char taglen = transform->ciphersuite_info->flags & |
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; |
size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen; |
/* |
* Prepare additional authenticated data |
*/ |
memcpy( add_data, ssl->out_ctr, 8 ); |
add_data[8] = ssl->out_msgtype; |
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, |
ssl->conf->transport, add_data + 9 ); |
add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; |
add_data[12] = ssl->out_msglen & 0xFF; |
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); |
/* |
* Generate IV |
*/ |
if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) |
{ |
/* GCM and CCM: fixed || explicit (=seqnum) */ |
memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); |
memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 ); |
memcpy( ssl->out_iv, ssl->out_ctr, 8 ); |
} |
else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) |
{ |
/* ChachaPoly: fixed XOR sequence number */ |
unsigned char i; |
memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); |
for( i = 0; i < 8; i++ ) |
iv[i+4] ^= ssl->out_ctr[i]; |
} |
else |
{ |
/* Reminder if we ever add an AEAD mode with a different size */ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", |
iv, transform->ivlen ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", |
ssl->out_iv, explicit_ivlen ); |
/* |
* Fix message length with added IV |
*/ |
enc_msg = ssl->out_msg; |
enc_msglen = ssl->out_msglen; |
ssl->out_msglen += explicit_ivlen; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " |
"including 0 bytes of padding", |
ssl->out_msglen ) ); |
/* |
* Encrypt and authenticate |
*/ |
if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, |
iv, transform->ivlen, |
add_data, 13, |
enc_msg, enc_msglen, |
enc_msg, &olen, |
enc_msg + enc_msglen, taglen ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); |
return( ret ); |
} |
if( olen != enc_msglen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
ssl->out_msglen += taglen; |
auth_done++; |
MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); |
} |
else |
#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ |
( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) |
if( mode == MBEDTLS_MODE_CBC ) |
{ |
int ret; |
unsigned char *enc_msg; |
size_t enc_msglen, padlen, olen = 0, i; |
padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % |
ssl->transform_out->ivlen; |
if( padlen == ssl->transform_out->ivlen ) |
padlen = 0; |
for( i = 0; i <= padlen; i++ ) |
ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; |
ssl->out_msglen += padlen + 1; |
enc_msglen = ssl->out_msglen; |
enc_msg = ssl->out_msg; |
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) |
/* |
* Prepend per-record IV for block cipher in TLS v1.1 and up as per |
* Method 1 (6.2.3.2. in RFC4346 and RFC5246) |
*/ |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) |
{ |
/* |
* Generate IV |
*/ |
ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc, |
ssl->transform_out->ivlen ); |
if( ret != 0 ) |
return( ret ); |
memcpy( ssl->out_iv, ssl->transform_out->iv_enc, |
ssl->transform_out->ivlen ); |
/* |
* Fix pointer positions and message length with added IV |
*/ |
enc_msg = ssl->out_msg; |
enc_msglen = ssl->out_msglen; |
ssl->out_msglen += ssl->transform_out->ivlen; |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " |
"including %d bytes of IV and %d bytes of padding", |
ssl->out_msglen, ssl->transform_out->ivlen, |
padlen + 1 ) ); |
if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, |
ssl->transform_out->iv_enc, |
ssl->transform_out->ivlen, |
enc_msg, enc_msglen, |
enc_msg, &olen ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); |
return( ret ); |
} |
if( enc_msglen != olen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) |
if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) |
{ |
/* |
* Save IV in SSL3 and TLS1 |
*/ |
memcpy( ssl->transform_out->iv_enc, |
ssl->transform_out->cipher_ctx_enc.iv, |
ssl->transform_out->ivlen ); |
} |
#endif |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
if( auth_done == 0 ) |
{ |
unsigned char mac[MBEDTLS_SSL_MAC_ADD]; |
/* |
* MAC(MAC_write_key, seq_num + |
* TLSCipherText.type + |
* TLSCipherText.version + |
* length_of( (IV +) ENC(...) ) + |
* IV + // except for TLS 1.0 |
* ENC(content + padding + padding_length)); |
*/ |
unsigned char pseudo_hdr[13]; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); |
memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 ); |
memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 ); |
pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF ); |
pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); |
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); |
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, |
ssl->out_iv, ssl->out_msglen ); |
mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); |
mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); |
memcpy( ssl->out_iv + ssl->out_msglen, mac, |
ssl->transform_out->maclen ); |
ssl->out_msglen += ssl->transform_out->maclen; |
auth_done++; |
} |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
} |
else |
#endif /* MBEDTLS_CIPHER_MODE_CBC && |
( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* Make extra sure authentication was performed, exactly once */ |
if( auth_done != 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); |
return( 0 ); |
} |
static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_cipher_mode_t mode; |
int auth_done = 0; |
#if defined(SSL_SOME_MODES_USE_MAC) |
size_t padlen = 0, correct = 1; |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); |
if( ssl->session_in == NULL || ssl->transform_in == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); |
if( ssl->in_msglen < ssl->transform_in->minlen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", |
ssl->in_msglen, ssl->transform_in->minlen ) ); |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
} |
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) |
if( mode == MBEDTLS_MODE_STREAM ) |
{ |
int ret; |
size_t olen = 0; |
padlen = 0; |
if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, |
ssl->transform_in->iv_dec, |
ssl->transform_in->ivlen, |
ssl->in_msg, ssl->in_msglen, |
ssl->in_msg, &olen ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); |
return( ret ); |
} |
if( ssl->in_msglen != olen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
else |
#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ |
#if defined(MBEDTLS_GCM_C) || \ |
defined(MBEDTLS_CCM_C) || \ |
defined(MBEDTLS_CHACHAPOLY_C) |
if( mode == MBEDTLS_MODE_GCM || |
mode == MBEDTLS_MODE_CCM || |
mode == MBEDTLS_MODE_CHACHAPOLY ) |
{ |
int ret; |
size_t dec_msglen, olen; |
unsigned char *dec_msg; |
unsigned char *dec_msg_result; |
unsigned char add_data[13]; |
unsigned char iv[12]; |
mbedtls_ssl_transform *transform = ssl->transform_in; |
unsigned char taglen = transform->ciphersuite_info->flags & |
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; |
size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; |
/* |
* Compute and update sizes |
*/ |
if( ssl->in_msglen < explicit_iv_len + taglen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " |
"+ taglen (%d)", ssl->in_msglen, |
explicit_iv_len, taglen ) ); |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
} |
dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; |
dec_msg = ssl->in_msg; |
dec_msg_result = ssl->in_msg; |
ssl->in_msglen = dec_msglen; |
/* |
* Prepare additional authenticated data |
*/ |
memcpy( add_data, ssl->in_ctr, 8 ); |
add_data[8] = ssl->in_msgtype; |
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, |
ssl->conf->transport, add_data + 9 ); |
add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; |
add_data[12] = ssl->in_msglen & 0xFF; |
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); |
/* |
* Prepare IV |
*/ |
if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) |
{ |
/* GCM and CCM: fixed || explicit (transmitted) */ |
memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); |
memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 ); |
} |
else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) |
{ |
/* ChachaPoly: fixed XOR sequence number */ |
unsigned char i; |
memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); |
for( i = 0; i < 8; i++ ) |
iv[i+4] ^= ssl->in_ctr[i]; |
} |
else |
{ |
/* Reminder if we ever add an AEAD mode with a different size */ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); |
/* |
* Decrypt and authenticate |
*/ |
if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, |
iv, transform->ivlen, |
add_data, 13, |
dec_msg, dec_msglen, |
dec_msg_result, &olen, |
dec_msg + dec_msglen, taglen ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); |
if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
return( ret ); |
} |
auth_done++; |
if( olen != dec_msglen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
else |
#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ |
( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) |
if( mode == MBEDTLS_MODE_CBC ) |
{ |
/* |
* Decrypt and check the padding |
*/ |
int ret; |
unsigned char *dec_msg; |
unsigned char *dec_msg_result; |
size_t dec_msglen; |
size_t minlen = 0; |
size_t olen = 0; |
/* |
* Check immediate ciphertext sanity |
*/ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) |
minlen += ssl->transform_in->ivlen; |
#endif |
if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || |
ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " |
"+ 1 ) ( + expl IV )", ssl->in_msglen, |
ssl->transform_in->ivlen, |
ssl->transform_in->maclen ) ); |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
} |
dec_msglen = ssl->in_msglen; |
dec_msg = ssl->in_msg; |
dec_msg_result = ssl->in_msg; |
/* |
* Authenticate before decrypt if enabled |
*/ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) |
{ |
unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; |
unsigned char pseudo_hdr[13]; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); |
dec_msglen -= ssl->transform_in->maclen; |
ssl->in_msglen -= ssl->transform_in->maclen; |
memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 ); |
memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 ); |
pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF ); |
pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); |
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); |
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, |
ssl->in_iv, ssl->in_msglen ); |
mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); |
mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, |
ssl->transform_in->maclen ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, |
ssl->transform_in->maclen ); |
if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, mac_expect, |
ssl->transform_in->maclen ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
} |
auth_done++; |
} |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
/* |
* Check length sanity |
*/ |
if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", |
ssl->in_msglen, ssl->transform_in->ivlen ) ); |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
} |
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) |
/* |
* Initialize for prepended IV for block cipher in TLS v1.1 and up |
*/ |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) |
{ |
unsigned char i; |
dec_msglen -= ssl->transform_in->ivlen; |
ssl->in_msglen -= ssl->transform_in->ivlen; |
for( i = 0; i < ssl->transform_in->ivlen; i++ ) |
ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ |
if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, |
ssl->transform_in->iv_dec, |
ssl->transform_in->ivlen, |
dec_msg, dec_msglen, |
dec_msg_result, &olen ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); |
return( ret ); |
} |
if( dec_msglen != olen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) |
if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) |
{ |
/* |
* Save IV in SSL3 and TLS1 |
*/ |
memcpy( ssl->transform_in->iv_dec, |
ssl->transform_in->cipher_ctx_dec.iv, |
ssl->transform_in->ivlen ); |
} |
#endif |
padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; |
if( ssl->in_msglen < ssl->transform_in->maclen + padlen && |
auth_done == 0 ) |
{ |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", |
ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); |
#endif |
padlen = 0; |
correct = 0; |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
if( padlen > ssl->transform_in->ivlen ) |
{ |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " |
"should be no more than %d", |
padlen, ssl->transform_in->ivlen ) ); |
#endif |
correct = 0; |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
/* |
* TLSv1+: always check the padding up to the first failure |
* and fake check up to 256 bytes of padding |
*/ |
size_t pad_count = 0, real_count = 1; |
size_t padding_idx = ssl->in_msglen - padlen; |
size_t i; |
/* |
* Padding is guaranteed to be incorrect if: |
* 1. padlen > ssl->in_msglen |
* |
* 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN + |
* ssl->transform_in->maclen |
* |
* In both cases we reset padding_idx to a safe value (0) to |
* prevent out-of-buffer reads. |
*/ |
correct &= ( padlen <= ssl->in_msglen ); |
correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN + |
ssl->transform_in->maclen ); |
padding_idx *= correct; |
for( i = 0; i < 256; i++ ) |
{ |
real_count &= ( i < padlen ); |
pad_count += real_count * |
( ssl->in_msg[padding_idx + i] == padlen - 1 ); |
} |
correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
if( padlen > 0 && correct == 0 ) |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); |
#endif |
padlen &= correct * 0x1FF; |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
ssl->in_msglen -= padlen; |
} |
else |
#endif /* MBEDTLS_CIPHER_MODE_CBC && |
( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", |
ssl->in_msg, ssl->in_msglen ); |
#endif |
/* |
* Authenticate if not done yet. |
* Compute the MAC regardless of the padding result (RFC4346, CBCTIME). |
*/ |
#if defined(SSL_SOME_MODES_USE_MAC) |
if( auth_done == 0 ) |
{ |
unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; |
ssl->in_msglen -= ssl->transform_in->maclen; |
ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); |
ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
ssl_mac( &ssl->transform_in->md_ctx_dec, |
ssl->transform_in->mac_dec, |
ssl->in_msg, ssl->in_msglen, |
ssl->in_ctr, ssl->in_msgtype, |
mac_expect ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
/* |
* Process MAC and always update for padlen afterwards to make |
* total time independent of padlen. |
* |
* Known timing attacks: |
* - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) |
* |
* To compensate for different timings for the MAC calculation |
* depending on how much padding was removed (which is determined |
* by padlen), process extra_run more blocks through the hash |
* function. |
* |
* The formula in the paper is |
* extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 ) |
* where L1 is the size of the header plus the decrypted message |
* plus CBC padding and L2 is the size of the header plus the |
* decrypted message. This is for an underlying hash function |
* with 64-byte blocks. |
* We use ( (Lx+8) / 64 ) to handle 'negative Lx' values |
* correctly. We round down instead of up, so -56 is the correct |
* value for our calculations instead of -55. |
* |
* Repeat the formula rather than defining a block_size variable. |
* This avoids requiring division by a variable at runtime |
* (which would be marginally less efficient and would require |
* linking an extra division function in some builds). |
*/ |
size_t j, extra_run = 0; |
/* |
* The next two sizes are the minimum and maximum values of |
* in_msglen over all padlen values. |
* |
* They're independent of padlen, since we previously did |
* in_msglen -= padlen. |
* |
* Note that max_len + maclen is never more than the buffer |
* length, as we previously did in_msglen -= maclen too. |
*/ |
const size_t max_len = ssl->in_msglen + padlen; |
const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; |
switch( ssl->transform_in->ciphersuite_info->mac ) |
{ |
#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \ |
defined(MBEDTLS_SHA256_C) |
case MBEDTLS_MD_MD5: |
case MBEDTLS_MD_SHA1: |
case MBEDTLS_MD_SHA256: |
/* 8 bytes of message size, 64-byte compression blocks */ |
extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - |
( 13 + ssl->in_msglen + 8 ) / 64; |
break; |
#endif |
#if defined(MBEDTLS_SHA512_C) |
case MBEDTLS_MD_SHA384: |
/* 16 bytes of message size, 128-byte compression blocks */ |
extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 - |
( 13 + ssl->in_msglen + 16 ) / 128; |
break; |
#endif |
default: |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
extra_run &= correct * 0xFF; |
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 ); |
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 ); |
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); |
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, |
ssl->in_msglen ); |
/* Make sure we access everything even when padlen > 0. This |
* makes the synchronisation requirements for just-in-time |
* Prime+Probe attacks much tighter and hopefully impractical. */ |
ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen ); |
mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); |
/* Call mbedtls_md_process at least once due to cache attacks |
* that observe whether md_process() was called of not */ |
for( j = 0; j < extra_run + 1; j++ ) |
mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); |
mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); |
/* Make sure we access all the memory that could contain the MAC, |
* before we check it in the next code block. This makes the |
* synchronisation requirements for just-in-time Prime+Probe |
* attacks much tighter and hopefully impractical. */ |
ssl_read_memory( ssl->in_msg + min_len, |
max_len - min_len + ssl->transform_in->maclen ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen, |
ssl->transform_in->maclen ); |
#endif |
if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect, |
ssl->transform_in->maclen ) != 0 ) |
{ |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); |
#endif |
correct = 0; |
} |
auth_done++; |
} |
/* |
* Finally check the correct flag |
*/ |
if( correct == 0 ) |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
#endif /* SSL_SOME_MODES_USE_MAC */ |
/* Make extra sure authentication was performed, exactly once */ |
if( auth_done != 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
if( ssl->in_msglen == 0 ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 |
&& ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) |
{ |
/* TLS v1.2 explicitly disallows zero-length messages which are not application data */ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
ssl->nb_zero++; |
/* |
* Three or more empty messages may be a DoS attack |
* (excessive CPU consumption). |
*/ |
if( ssl->nb_zero > 3 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " |
"messages, possible DoS attack" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
} |
} |
else |
ssl->nb_zero = 0; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
; /* in_ctr read from peer, not maintained internally */ |
} |
else |
#endif |
{ |
unsigned char i; |
for( i = 8; i > ssl_ep_len( ssl ); i-- ) |
if( ++ssl->in_ctr[i - 1] != 0 ) |
break; |
/* The loop goes to its end iff the counter is wrapping */ |
if( i == ssl_ep_len( ssl ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); |
return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); |
return( 0 ); |
} |
#undef MAC_NONE |
#undef MAC_PLAINTEXT |
#undef MAC_CIPHERTEXT |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
/* |
* Compression/decompression functions |
*/ |
static int ssl_compress_buf( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
unsigned char *msg_post = ssl->out_msg; |
ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; |
size_t len_pre = ssl->out_msglen; |
unsigned char *msg_pre = ssl->compress_buf; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); |
if( len_pre == 0 ) |
return( 0 ); |
memcpy( msg_pre, ssl->out_msg, len_pre ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", |
ssl->out_msglen ) ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", |
ssl->out_msg, ssl->out_msglen ); |
ssl->transform_out->ctx_deflate.next_in = msg_pre; |
ssl->transform_out->ctx_deflate.avail_in = len_pre; |
ssl->transform_out->ctx_deflate.next_out = msg_post; |
ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written; |
ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); |
if( ret != Z_OK ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); |
return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); |
} |
ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN - |
ssl->transform_out->ctx_deflate.avail_out - bytes_written; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", |
ssl->out_msglen ) ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", |
ssl->out_msg, ssl->out_msglen ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); |
return( 0 ); |
} |
static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
unsigned char *msg_post = ssl->in_msg; |
ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; |
size_t len_pre = ssl->in_msglen; |
unsigned char *msg_pre = ssl->compress_buf; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); |
if( len_pre == 0 ) |
return( 0 ); |
memcpy( msg_pre, ssl->in_msg, len_pre ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", |
ssl->in_msglen ) ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", |
ssl->in_msg, ssl->in_msglen ); |
ssl->transform_in->ctx_inflate.next_in = msg_pre; |
ssl->transform_in->ctx_inflate.avail_in = len_pre; |
ssl->transform_in->ctx_inflate.next_out = msg_post; |
ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN - |
header_bytes; |
ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); |
if( ret != Z_OK ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); |
return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); |
} |
ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN - |
ssl->transform_in->ctx_inflate.avail_out - header_bytes; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", |
ssl->in_msglen ) ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", |
ssl->in_msg, ssl->in_msglen ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_ZLIB_SUPPORT */ |
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) |
static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) |
{ |
/* If renegotiation is not enforced, retransmit until we would reach max |
* timeout if we were using the usual handshake doubling scheme */ |
if( ssl->conf->renego_max_records < 0 ) |
{ |
uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; |
unsigned char doublings = 1; |
while( ratio != 0 ) |
{ |
++doublings; |
ratio >>= 1; |
} |
if( ++ssl->renego_records_seen > doublings ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); |
return( 0 ); |
} |
} |
return( ssl_write_hello_request( ssl ) ); |
} |
#endif |
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ |
/* |
* Fill the input message buffer by appending data to it. |
* The amount of data already fetched is in ssl->in_left. |
* |
* If we return 0, is it guaranteed that (at least) nb_want bytes are |
* available (from this read and/or a previous one). Otherwise, an error code |
* is returned (possibly EOF or WANT_READ). |
* |
* With stream transport (TLS) on success ssl->in_left == nb_want, but |
* with datagram transport (DTLS) on success ssl->in_left >= nb_want, |
* since we always read a whole datagram at once. |
* |
* For DTLS, it is up to the caller to set ssl->next_record_offset when |
* they're done reading a record. |
*/ |
int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) |
{ |
int ret; |
size_t len; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); |
if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " |
"or mbedtls_ssl_set_bio()" ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
uint32_t timeout; |
/* Just to be sure */ |
if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " |
"mbedtls_ssl_set_timer_cb() for DTLS" ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
/* |
* The point is, we need to always read a full datagram at once, so we |
* sometimes read more then requested, and handle the additional data. |
* It could be the rest of the current record (while fetching the |
* header) and/or some other records in the same datagram. |
*/ |
/* |
* Move to the next record in the already read datagram if applicable |
*/ |
if( ssl->next_record_offset != 0 ) |
{ |
if( ssl->in_left < ssl->next_record_offset ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
ssl->in_left -= ssl->next_record_offset; |
if( ssl->in_left != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", |
ssl->next_record_offset ) ); |
memmove( ssl->in_hdr, |
ssl->in_hdr + ssl->next_record_offset, |
ssl->in_left ); |
} |
ssl->next_record_offset = 0; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", |
ssl->in_left, nb_want ) ); |
/* |
* Done if we already have enough data. |
*/ |
if( nb_want <= ssl->in_left) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); |
return( 0 ); |
} |
/* |
* A record can't be split across datagrams. If we need to read but |
* are not at the beginning of a new record, the caller did something |
* wrong. |
*/ |
if( ssl->in_left != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* |
* Don't even try to read if time's out already. |
* This avoids by-passing the timer when repeatedly receiving messages |
* that will end up being dropped. |
*/ |
if( ssl_check_timer( ssl ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); |
ret = MBEDTLS_ERR_SSL_TIMEOUT; |
} |
else |
{ |
len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) |
timeout = ssl->handshake->retransmit_timeout; |
else |
timeout = ssl->conf->read_timeout; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); |
if( ssl->f_recv_timeout != NULL ) |
ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, |
timeout ); |
else |
ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); |
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); |
if( ret == 0 ) |
return( MBEDTLS_ERR_SSL_CONN_EOF ); |
} |
if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); |
ssl_set_timer( ssl, 0 ); |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) |
{ |
if( ssl_double_retransmit_timeout( ssl ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); |
return( MBEDTLS_ERR_SSL_TIMEOUT ); |
} |
if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); |
return( ret ); |
} |
return( MBEDTLS_ERR_SSL_WANT_READ ); |
} |
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) |
else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) |
{ |
if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); |
return( ret ); |
} |
return( MBEDTLS_ERR_SSL_WANT_READ ); |
} |
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ |
} |
if( ret < 0 ) |
return( ret ); |
ssl->in_left = ret; |
} |
else |
#endif |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", |
ssl->in_left, nb_want ) ); |
while( ssl->in_left < nb_want ) |
{ |
len = nb_want - ssl->in_left; |
if( ssl_check_timer( ssl ) != 0 ) |
ret = MBEDTLS_ERR_SSL_TIMEOUT; |
else |
{ |
if( ssl->f_recv_timeout != NULL ) |
{ |
ret = ssl->f_recv_timeout( ssl->p_bio, |
ssl->in_hdr + ssl->in_left, len, |
ssl->conf->read_timeout ); |
} |
else |
{ |
ret = ssl->f_recv( ssl->p_bio, |
ssl->in_hdr + ssl->in_left, len ); |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", |
ssl->in_left, nb_want ) ); |
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); |
if( ret == 0 ) |
return( MBEDTLS_ERR_SSL_CONN_EOF ); |
if( ret < 0 ) |
return( ret ); |
if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, |
( "f_recv returned %d bytes but only %lu were requested", |
ret, (unsigned long)len ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
ssl->in_left += ret; |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); |
return( 0 ); |
} |
/* |
* Flush any data not yet written |
*/ |
int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
unsigned char *buf; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); |
if( ssl->f_send == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " |
"or mbedtls_ssl_set_bio()" ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
/* Avoid incrementing counter if data is flushed */ |
if( ssl->out_left == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); |
return( 0 ); |
} |
while( ssl->out_left > 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", |
mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); |
buf = ssl->out_hdr - ssl->out_left; |
ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); |
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); |
if( ret <= 0 ) |
return( ret ); |
if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, |
( "f_send returned %d bytes but only %lu bytes were sent", |
ret, (unsigned long)ssl->out_left ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
ssl->out_left -= ret; |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
ssl->out_hdr = ssl->out_buf; |
} |
else |
#endif |
{ |
ssl->out_hdr = ssl->out_buf + 8; |
} |
ssl_update_out_pointers( ssl, ssl->transform_out ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); |
return( 0 ); |
} |
/* |
* Functions to handle the DTLS retransmission state machine |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
/* |
* Append current handshake message to current outgoing flight |
*/ |
static int ssl_flight_append( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_flight_item *msg; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", |
ssl->out_msg, ssl->out_msglen ); |
/* Allocate space for current message */ |
if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", |
sizeof( mbedtls_ssl_flight_item ) ) ); |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); |
mbedtls_free( msg ); |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
/* Copy current handshake message with headers */ |
memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); |
msg->len = ssl->out_msglen; |
msg->type = ssl->out_msgtype; |
msg->next = NULL; |
/* Append to the current flight */ |
if( ssl->handshake->flight == NULL ) |
ssl->handshake->flight = msg; |
else |
{ |
mbedtls_ssl_flight_item *cur = ssl->handshake->flight; |
while( cur->next != NULL ) |
cur = cur->next; |
cur->next = msg; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); |
return( 0 ); |
} |
/* |
* Free the current flight of handshake messages |
*/ |
static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) |
{ |
mbedtls_ssl_flight_item *cur = flight; |
mbedtls_ssl_flight_item *next; |
while( cur != NULL ) |
{ |
next = cur->next; |
mbedtls_free( cur->p ); |
mbedtls_free( cur ); |
cur = next; |
} |
} |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); |
#endif |
/* |
* Swap transform_out and out_ctr with the alternative ones |
*/ |
static int ssl_swap_epochs( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_transform *tmp_transform; |
unsigned char tmp_out_ctr[8]; |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
int ret; |
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ |
if( ssl->transform_out == ssl->handshake->alt_transform_out ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); |
/* Swap transforms */ |
tmp_transform = ssl->transform_out; |
ssl->transform_out = ssl->handshake->alt_transform_out; |
ssl->handshake->alt_transform_out = tmp_transform; |
/* Swap epoch + sequence_number */ |
memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); |
memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); |
memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); |
/* Adjust to the newly activated transform */ |
ssl_update_out_pointers( ssl, ssl->transform_out ); |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_activate != NULL ) |
{ |
if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); |
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); |
} |
} |
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ |
return( 0 ); |
} |
/* |
* Retransmit the current flight of messages. |
*/ |
int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) |
{ |
int ret = 0; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); |
ret = mbedtls_ssl_flight_transmit( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); |
return( ret ); |
} |
/* |
* Transmit or retransmit the current flight of messages. |
* |
* Need to remember the current message in case flush_output returns |
* WANT_WRITE, causing us to exit this function and come back later. |
* This function must be called until state is no longer SENDING. |
*/ |
int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); |
if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); |
ssl->handshake->cur_msg = ssl->handshake->flight; |
ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; |
if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) |
return( ret ); |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; |
} |
while( ssl->handshake->cur_msg != NULL ) |
{ |
size_t max_frag_len; |
const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; |
int const is_finished = |
( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && |
cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); |
uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? |
SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; |
/* Swap epochs before sending Finished: we can't do it after |
* sending ChangeCipherSpec, in case write returns WANT_READ. |
* Must be done before copying, may change out_msg pointer */ |
if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); |
if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) |
return( ret ); |
} |
ret = ssl_get_remaining_payload_in_datagram( ssl ); |
if( ret < 0 ) |
return( ret ); |
max_frag_len = (size_t) ret; |
/* CCS is copied as is, while HS messages may need fragmentation */ |
if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) |
{ |
if( max_frag_len == 0 ) |
{ |
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
return( ret ); |
continue; |
} |
memcpy( ssl->out_msg, cur->p, cur->len ); |
ssl->out_msglen = cur->len; |
ssl->out_msgtype = cur->type; |
/* Update position inside current message */ |
ssl->handshake->cur_msg_p += cur->len; |
} |
else |
{ |
const unsigned char * const p = ssl->handshake->cur_msg_p; |
const size_t hs_len = cur->len - 12; |
const size_t frag_off = p - ( cur->p + 12 ); |
const size_t rem_len = hs_len - frag_off; |
size_t cur_hs_frag_len, max_hs_frag_len; |
if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) |
{ |
if( is_finished ) |
{ |
if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) |
return( ret ); |
} |
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
return( ret ); |
continue; |
} |
max_hs_frag_len = max_frag_len - 12; |
cur_hs_frag_len = rem_len > max_hs_frag_len ? |
max_hs_frag_len : rem_len; |
if( frag_off == 0 && cur_hs_frag_len != hs_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", |
(unsigned) cur_hs_frag_len, |
(unsigned) max_hs_frag_len ) ); |
} |
/* Messages are stored with handshake headers as if not fragmented, |
* copy beginning of headers then fill fragmentation fields. |
* Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ |
memcpy( ssl->out_msg, cur->p, 6 ); |
ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff ); |
ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); |
ssl->out_msg[8] = ( ( frag_off ) & 0xff ); |
ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); |
ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); |
ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); |
/* Copy the handshake message content and set records fields */ |
memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); |
ssl->out_msglen = cur_hs_frag_len + 12; |
ssl->out_msgtype = cur->type; |
/* Update position inside current message */ |
ssl->handshake->cur_msg_p += cur_hs_frag_len; |
} |
/* If done with the current message move to the next one if any */ |
if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) |
{ |
if( cur->next != NULL ) |
{ |
ssl->handshake->cur_msg = cur->next; |
ssl->handshake->cur_msg_p = cur->next->p + 12; |
} |
else |
{ |
ssl->handshake->cur_msg = NULL; |
ssl->handshake->cur_msg_p = NULL; |
} |
} |
/* Actually send the message out */ |
if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); |
return( ret ); |
} |
} |
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
return( ret ); |
/* Update state and set timer */ |
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; |
else |
{ |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; |
ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); |
return( 0 ); |
} |
/* |
* To be called when the last message of an incoming flight is received. |
*/ |
void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) |
{ |
/* We won't need to resend that one any more */ |
ssl_flight_free( ssl->handshake->flight ); |
ssl->handshake->flight = NULL; |
ssl->handshake->cur_msg = NULL; |
/* The next incoming flight will start with this msg_seq */ |
ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; |
/* We don't want to remember CCS's across flight boundaries. */ |
ssl->handshake->buffering.seen_ccs = 0; |
/* Clear future message buffering structure. */ |
ssl_buffering_free( ssl ); |
/* Cancel timer */ |
ssl_set_timer( ssl, 0 ); |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && |
ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) |
{ |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; |
} |
else |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; |
} |
/* |
* To be called when the last message of an outgoing flight is send. |
*/ |
void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) |
{ |
ssl_reset_retransmit_timeout( ssl ); |
ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && |
ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) |
{ |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; |
} |
else |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
/* |
* Handshake layer functions |
*/ |
/* |
* Write (DTLS: or queue) current handshake (including CCS) message. |
* |
* - fill in handshake headers |
* - update handshake checksum |
* - DTLS: save message for resending |
* - then pass to the record layer |
* |
* DTLS: except for HelloRequest, messages are only queued, and will only be |
* actually sent when calling flight_transmit() or resend(). |
* |
* Inputs: |
* - ssl->out_msglen: 4 + actual handshake message len |
* (4 is the size of handshake headers for TLS) |
* - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) |
* - ssl->out_msg + 4: the handshake message body |
* |
* Outputs, ie state before passing to flight_append() or write_record(): |
* - ssl->out_msglen: the length of the record contents |
* (including handshake headers but excluding record headers) |
* - ssl->out_msg: the record contents (handshake headers + content) |
*/ |
int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
const size_t hs_len = ssl->out_msglen - 4; |
const unsigned char hs_type = ssl->out_msg[0]; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); |
/* |
* Sanity checks |
*/ |
if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && |
ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) |
{ |
/* In SSLv3, the client might send a NoCertificate alert. */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) |
if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && |
ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && |
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) |
#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
/* Whenever we send anything different from a |
* HelloRequest we should be in a handshake - double check. */ |
if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && |
hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && |
ssl->handshake == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake != NULL && |
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#endif |
/* Double-check that we did not exceed the bounds |
* of the outgoing record buffer. |
* This should never fail as the various message |
* writing functions must obey the bounds of the |
* outgoing record buffer, but better be safe. |
* |
* Note: We deliberately do not check for the MTU or MFL here. |
*/ |
if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " |
"size %u, maximum %u", |
(unsigned) ssl->out_msglen, |
(unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* |
* Fill handshake headers |
*/ |
if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
ssl->out_msg[1] = (unsigned char)( hs_len >> 16 ); |
ssl->out_msg[2] = (unsigned char)( hs_len >> 8 ); |
ssl->out_msg[3] = (unsigned char)( hs_len ); |
/* |
* DTLS has additional fields in the Handshake layer, |
* between the length field and the actual payload: |
* uint16 message_seq; |
* uint24 fragment_offset; |
* uint24 fragment_length; |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
/* Make room for the additional DTLS fields */ |
if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " |
"size %u, maximum %u", |
(unsigned) ( hs_len ), |
(unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); |
ssl->out_msglen += 8; |
/* Write message_seq and update it, except for HelloRequest */ |
if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) |
{ |
ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; |
ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; |
++( ssl->handshake->out_msg_seq ); |
} |
else |
{ |
ssl->out_msg[4] = 0; |
ssl->out_msg[5] = 0; |
} |
/* Handshake hashes are computed without fragmentation, |
* so set frag_offset = 0 and frag_len = hs_len for now */ |
memset( ssl->out_msg + 6, 0x00, 3 ); |
memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
/* Update running hashes of handshake messages seen */ |
if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) |
ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); |
} |
/* Either send now, or just save to be sent (and resent) later */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && |
hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) |
{ |
if( ( ret = ssl_flight_append( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); |
return( ret ); |
} |
} |
else |
#endif |
{ |
if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); |
return( ret ); |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); |
return( 0 ); |
} |
/* |
* Record layer functions |
*/ |
/* |
* Write current record. |
* |
* Uses: |
* - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) |
* - ssl->out_msglen: length of the record content (excl headers) |
* - ssl->out_msg: record content |
*/ |
int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) |
{ |
int ret, done = 0; |
size_t len = ssl->out_msglen; |
uint8_t flush = force_flush; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
if( ssl->transform_out != NULL && |
ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) |
{ |
if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); |
return( ret ); |
} |
len = ssl->out_msglen; |
} |
#endif /*MBEDTLS_ZLIB_SUPPORT */ |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_write != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); |
ret = mbedtls_ssl_hw_record_write( ssl ); |
if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); |
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); |
} |
if( ret == 0 ) |
done = 1; |
} |
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ |
if( !done ) |
{ |
unsigned i; |
size_t protected_record_size; |
ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; |
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, |
ssl->conf->transport, ssl->out_hdr + 1 ); |
memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); |
ssl->out_len[0] = (unsigned char)( len >> 8 ); |
ssl->out_len[1] = (unsigned char)( len ); |
if( ssl->transform_out != NULL ) |
{ |
if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); |
return( ret ); |
} |
len = ssl->out_msglen; |
ssl->out_len[0] = (unsigned char)( len >> 8 ); |
ssl->out_len[1] = (unsigned char)( len ); |
} |
protected_record_size = len + mbedtls_ssl_hdr_len( ssl ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
/* In case of DTLS, double-check that we don't exceed |
* the remaining space in the datagram. */ |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
ret = ssl_get_remaining_space_in_datagram( ssl ); |
if( ret < 0 ) |
return( ret ); |
if( protected_record_size > (size_t) ret ) |
{ |
/* Should never happen */ |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " |
"version = [%d:%d], msglen = %d", |
ssl->out_hdr[0], ssl->out_hdr[1], |
ssl->out_hdr[2], len ) ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", |
ssl->out_hdr, protected_record_size ); |
ssl->out_left += protected_record_size; |
ssl->out_hdr += protected_record_size; |
ssl_update_out_pointers( ssl, ssl->transform_out ); |
for( i = 8; i > ssl_ep_len( ssl ); i-- ) |
if( ++ssl->cur_out_ctr[i - 1] != 0 ) |
break; |
/* The loop goes to its end iff the counter is wrapping */ |
if( i == ssl_ep_len( ssl ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); |
return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); |
} |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
flush == SSL_DONT_FORCE_FLUSH ) |
{ |
size_t remaining; |
ret = ssl_get_remaining_payload_in_datagram( ssl ); |
if( ret < 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", |
ret ); |
return( ret ); |
} |
remaining = (size_t) ret; |
if( remaining == 0 ) |
{ |
flush = SSL_FORCE_FLUSH; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
if( ( flush == SSL_FORCE_FLUSH ) && |
( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) |
{ |
if( ssl->in_msglen < ssl->in_hslen || |
memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || |
memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) |
{ |
return( 1 ); |
} |
return( 0 ); |
} |
static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) |
{ |
return( ( ssl->in_msg[9] << 16 ) | |
( ssl->in_msg[10] << 8 ) | |
ssl->in_msg[11] ); |
} |
static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) |
{ |
return( ( ssl->in_msg[6] << 16 ) | |
( ssl->in_msg[7] << 8 ) | |
ssl->in_msg[8] ); |
} |
static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) |
{ |
uint32_t msg_len, frag_off, frag_len; |
msg_len = ssl_get_hs_total_len( ssl ); |
frag_off = ssl_get_hs_frag_off( ssl ); |
frag_len = ssl_get_hs_frag_len( ssl ); |
if( frag_off > msg_len ) |
return( -1 ); |
if( frag_len > msg_len - frag_off ) |
return( -1 ); |
if( frag_len + 12 > ssl->in_msglen ) |
return( -1 ); |
return( 0 ); |
} |
/* |
* Mark bits in bitmask (used for DTLS HS reassembly) |
*/ |
static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) |
{ |
unsigned int start_bits, end_bits; |
start_bits = 8 - ( offset % 8 ); |
if( start_bits != 8 ) |
{ |
size_t first_byte_idx = offset / 8; |
/* Special case */ |
if( len <= start_bits ) |
{ |
for( ; len != 0; len-- ) |
mask[first_byte_idx] |= 1 << ( start_bits - len ); |
/* Avoid potential issues with offset or len becoming invalid */ |
return; |
} |
offset += start_bits; /* Now offset % 8 == 0 */ |
len -= start_bits; |
for( ; start_bits != 0; start_bits-- ) |
mask[first_byte_idx] |= 1 << ( start_bits - 1 ); |
} |
end_bits = len % 8; |
if( end_bits != 0 ) |
{ |
size_t last_byte_idx = ( offset + len ) / 8; |
len -= end_bits; /* Now len % 8 == 0 */ |
for( ; end_bits != 0; end_bits-- ) |
mask[last_byte_idx] |= 1 << ( 8 - end_bits ); |
} |
memset( mask + offset / 8, 0xFF, len / 8 ); |
} |
/* |
* Check that bitmask is full |
*/ |
static int ssl_bitmask_check( unsigned char *mask, size_t len ) |
{ |
size_t i; |
for( i = 0; i < len / 8; i++ ) |
if( mask[i] != 0xFF ) |
return( -1 ); |
for( i = 0; i < len % 8; i++ ) |
if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) |
return( -1 ); |
return( 0 ); |
} |
/* msg_len does not include the handshake header */ |
static size_t ssl_get_reassembly_buffer_size( size_t msg_len, |
unsigned add_bitmap ) |
{ |
size_t alloc_len; |
alloc_len = 12; /* Handshake header */ |
alloc_len += msg_len; /* Content buffer */ |
if( add_bitmap ) |
alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ |
return( alloc_len ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) |
{ |
return( ( ssl->in_msg[1] << 16 ) | |
( ssl->in_msg[2] << 8 ) | |
ssl->in_msg[3] ); |
} |
int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) |
{ |
if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", |
ssl->in_msglen ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" |
" %d, type = %d, hslen = %d", |
ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
int ret; |
unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; |
if( ssl_check_hs_header( ssl ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
if( ssl->handshake != NULL && |
( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && |
recv_msg_seq != ssl->handshake->in_msg_seq ) || |
( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && |
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) |
{ |
if( recv_msg_seq > ssl->handshake->in_msg_seq ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", |
recv_msg_seq, |
ssl->handshake->in_msg_seq ) ); |
return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); |
} |
/* Retransmit only on last message from previous flight, to avoid |
* too many retransmissions. |
* Besides, No sane server ever retransmits HelloVerifyRequest */ |
if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && |
ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " |
"message_seq = %d, start_of_flight = %d", |
recv_msg_seq, |
ssl->handshake->in_flight_start_seq ) ); |
if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); |
return( ret ); |
} |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " |
"message_seq = %d, expected = %d", |
recv_msg_seq, |
ssl->handshake->in_msg_seq ) ); |
} |
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); |
} |
/* Wait until message completion to increment in_msg_seq */ |
/* Message reassembly is handled alongside buffering of future |
* messages; the commonality is that both handshake fragments and |
* future messages cannot be forwarded immediately to the |
* handshake logic layer. */ |
if( ssl_hs_is_proper_fragment( ssl ) == 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); |
return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
/* With TLS we don't handle fragmentation (for now) */ |
if( ssl->in_msglen < ssl->in_hslen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); |
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); |
} |
return( 0 ); |
} |
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) |
{ |
ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); |
} |
/* Handshake message is complete, increment counter */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake != NULL ) |
{ |
unsigned offset; |
mbedtls_ssl_hs_buffer *hs_buf; |
/* Increment handshake sequence number */ |
hs->in_msg_seq++; |
/* |
* Clear up handshake buffering and reassembly structure. |
*/ |
/* Free first entry */ |
ssl_buffering_free_slot( ssl, 0 ); |
/* Shift all other entries */ |
for( offset = 0, hs_buf = &hs->buffering.hs[0]; |
offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; |
offset++, hs_buf++ ) |
{ |
*hs_buf = *(hs_buf + 1); |
} |
/* Create a fresh last entry */ |
memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); |
} |
#endif |
} |
/* |
* DTLS anti-replay: RFC 6347 4.1.2.6 |
* |
* in_window is a field of bits numbered from 0 (lsb) to 63 (msb). |
* Bit n is set iff record number in_window_top - n has been seen. |
* |
* Usually, in_window_top is the last record number seen and the lsb of |
* in_window is set. The only exception is the initial state (record number 0 |
* not seen yet). |
*/ |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) |
{ |
ssl->in_window_top = 0; |
ssl->in_window = 0; |
} |
static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) |
{ |
return( ( (uint64_t) buf[0] << 40 ) | |
( (uint64_t) buf[1] << 32 ) | |
( (uint64_t) buf[2] << 24 ) | |
( (uint64_t) buf[3] << 16 ) | |
( (uint64_t) buf[4] << 8 ) | |
( (uint64_t) buf[5] ) ); |
} |
/* |
* Return 0 if sequence number is acceptable, -1 otherwise |
*/ |
int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) |
{ |
uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); |
uint64_t bit; |
if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) |
return( 0 ); |
if( rec_seqnum > ssl->in_window_top ) |
return( 0 ); |
bit = ssl->in_window_top - rec_seqnum; |
if( bit >= 64 ) |
return( -1 ); |
if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) |
return( -1 ); |
return( 0 ); |
} |
/* |
* Update replay window on new validated record |
*/ |
void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) |
{ |
uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); |
if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) |
return; |
if( rec_seqnum > ssl->in_window_top ) |
{ |
/* Update window_top and the contents of the window */ |
uint64_t shift = rec_seqnum - ssl->in_window_top; |
if( shift >= 64 ) |
ssl->in_window = 1; |
else |
{ |
ssl->in_window <<= shift; |
ssl->in_window |= 1; |
} |
ssl->in_window_top = rec_seqnum; |
} |
else |
{ |
/* Mark that number as seen in the current window */ |
uint64_t bit = ssl->in_window_top - rec_seqnum; |
if( bit < 64 ) /* Always true, but be extra sure */ |
ssl->in_window |= (uint64_t) 1 << bit; |
} |
} |
#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ |
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) |
/* Forward declaration */ |
static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); |
/* |
* Without any SSL context, check if a datagram looks like a ClientHello with |
* a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. |
* Both input and output include full DTLS headers. |
* |
* - if cookie is valid, return 0 |
* - if ClientHello looks superficially valid but cookie is not, |
* fill obuf and set olen, then |
* return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED |
* - otherwise return a specific error code |
*/ |
static int ssl_check_dtls_clihlo_cookie( |
mbedtls_ssl_cookie_write_t *f_cookie_write, |
mbedtls_ssl_cookie_check_t *f_cookie_check, |
void *p_cookie, |
const unsigned char *cli_id, size_t cli_id_len, |
const unsigned char *in, size_t in_len, |
unsigned char *obuf, size_t buf_len, size_t *olen ) |
{ |
size_t sid_len, cookie_len; |
unsigned char *p; |
if( f_cookie_write == NULL || f_cookie_check == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
/* |
* Structure of ClientHello with record and handshake headers, |
* and expected values. We don't need to check a lot, more checks will be |
* done when actually parsing the ClientHello - skipping those checks |
* avoids code duplication and does not make cookie forging any easier. |
* |
* 0-0 ContentType type; copied, must be handshake |
* 1-2 ProtocolVersion version; copied |
* 3-4 uint16 epoch; copied, must be 0 |
* 5-10 uint48 sequence_number; copied |
* 11-12 uint16 length; (ignored) |
* |
* 13-13 HandshakeType msg_type; (ignored) |
* 14-16 uint24 length; (ignored) |
* 17-18 uint16 message_seq; copied |
* 19-21 uint24 fragment_offset; copied, must be 0 |
* 22-24 uint24 fragment_length; (ignored) |
* |
* 25-26 ProtocolVersion client_version; (ignored) |
* 27-58 Random random; (ignored) |
* 59-xx SessionID session_id; 1 byte len + sid_len content |
* 60+ opaque cookie<0..2^8-1>; 1 byte len + content |
* ... |
* |
* Minimum length is 61 bytes. |
*/ |
if( in_len < 61 || |
in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || |
in[3] != 0 || in[4] != 0 || |
in[19] != 0 || in[20] != 0 || in[21] != 0 ) |
{ |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
} |
sid_len = in[59]; |
if( sid_len > in_len - 61 ) |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
cookie_len = in[60 + sid_len]; |
if( cookie_len > in_len - 60 ) |
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); |
if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, |
cli_id, cli_id_len ) == 0 ) |
{ |
/* Valid cookie */ |
return( 0 ); |
} |
/* |
* If we get here, we've got an invalid cookie, let's prepare HVR. |
* |
* 0-0 ContentType type; copied |
* 1-2 ProtocolVersion version; copied |
* 3-4 uint16 epoch; copied |
* 5-10 uint48 sequence_number; copied |
* 11-12 uint16 length; olen - 13 |
* |
* 13-13 HandshakeType msg_type; hello_verify_request |
* 14-16 uint24 length; olen - 25 |
* 17-18 uint16 message_seq; copied |
* 19-21 uint24 fragment_offset; copied |
* 22-24 uint24 fragment_length; olen - 25 |
* |
* 25-26 ProtocolVersion server_version; 0xfe 0xff |
* 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie |
* |
* Minimum length is 28. |
*/ |
if( buf_len < 28 ) |
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); |
/* Copy most fields and adapt others */ |
memcpy( obuf, in, 25 ); |
obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; |
obuf[25] = 0xfe; |
obuf[26] = 0xff; |
/* Generate and write actual cookie */ |
p = obuf + 28; |
if( f_cookie_write( p_cookie, |
&p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) |
{ |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
*olen = p - obuf; |
/* Go back and fill length fields */ |
obuf[27] = (unsigned char)( *olen - 28 ); |
obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); |
obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); |
obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); |
obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); |
obuf[12] = (unsigned char)( ( *olen - 13 ) ); |
return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); |
} |
/* |
* Handle possible client reconnect with the same UDP quadruplet |
* (RFC 6347 Section 4.2.8). |
* |
* Called by ssl_parse_record_header() in case we receive an epoch 0 record |
* that looks like a ClientHello. |
* |
* - if the input looks like a ClientHello without cookies, |
* send back HelloVerifyRequest, then |
* return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED |
* - if the input looks like a ClientHello with a valid cookie, |
* reset the session of the current context, and |
* return MBEDTLS_ERR_SSL_CLIENT_RECONNECT |
* - if anything goes wrong, return a specific error code |
* |
* mbedtls_ssl_read_record() will ignore the record if anything else than |
* MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function |
* cannot not return 0. |
*/ |
static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
size_t len; |
ret = ssl_check_dtls_clihlo_cookie( |
ssl->conf->f_cookie_write, |
ssl->conf->f_cookie_check, |
ssl->conf->p_cookie, |
ssl->cli_id, ssl->cli_id_len, |
ssl->in_buf, ssl->in_left, |
ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); |
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); |
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) |
{ |
int send_ret; |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", |
ssl->out_buf, len ); |
/* Don't check write errors as we can't do anything here. |
* If the error is permanent we'll catch it later, |
* if it's not, then hopefully it'll work next time. */ |
send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len ); |
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret ); |
(void) send_ret; |
return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); |
} |
if( ret == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) ); |
if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); |
return( ret ); |
} |
return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); |
} |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ |
/* |
* ContentType type; |
* ProtocolVersion version; |
* uint16 epoch; // DTLS only |
* uint48 sequence_number; // DTLS only |
* uint16 length; |
* |
* Return 0 if header looks sane (and, for DTLS, the record is expected) |
* MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, |
* MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. |
* |
* With DTLS, mbedtls_ssl_read_record() will: |
* 1. proceed with the record if this function returns 0 |
* 2. drop only the current record if this function returns UNEXPECTED_RECORD |
* 3. return CLIENT_RECONNECT if this function return that value |
* 4. drop the whole datagram if this function returns anything else. |
* Point 2 is needed when the peer is resending, and we have already received |
* the first record from a datagram but are still waiting for the others. |
*/ |
static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) |
{ |
int major_ver, minor_ver; |
MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); |
ssl->in_msgtype = ssl->in_hdr[0]; |
ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; |
mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " |
"version = [%d:%d], msglen = %d", |
ssl->in_msgtype, |
major_ver, minor_ver, ssl->in_msglen ) ); |
/* Check record type */ |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && |
ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT && |
ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && |
ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
/* Silently ignore invalid DTLS records as recommended by RFC 6347 |
* Section 4.1.2.7 */ |
if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
/* Check version */ |
if( major_ver != ssl->major_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
if( minor_ver > ssl->conf->max_minor_ver ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
/* Check length against the size of our buffer */ |
if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN |
- (size_t)( ssl->in_msg - ssl->in_buf ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
/* |
* DTLS-related tests. |
* Check epoch before checking length constraint because |
* the latter varies with the epoch. E.g., if a ChangeCipherSpec |
* message gets duplicated before the corresponding Finished message, |
* the second ChangeCipherSpec should be discarded because it belongs |
* to an old epoch, but not because its length is shorter than |
* the minimum record length for packets using the new record transform. |
* Note that these two kinds of failures are handled differently, |
* as an unexpected record is silently skipped but an invalid |
* record leads to the entire datagram being dropped. |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; |
/* Check epoch (and sequence number) with DTLS */ |
if( rec_epoch != ssl->in_epoch ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " |
"expected %d, received %d", |
ssl->in_epoch, rec_epoch ) ); |
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) |
/* |
* Check for an epoch 0 ClientHello. We can't use in_msg here to |
* access the first byte of record content (handshake type), as we |
* have an active transform (possibly iv_len != 0), so use the |
* fact that the record header len is 13 instead. |
*/ |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && |
rec_epoch == 0 && |
ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && |
ssl->in_left > 13 && |
ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " |
"from the same port" ) ); |
return( ssl_handle_possible_reconnect( ssl ) ); |
} |
else |
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ |
{ |
/* Consider buffering the record. */ |
if( rec_epoch == (unsigned int) ssl->in_epoch + 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); |
return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); |
} |
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); |
} |
} |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
/* Replay detection only works for the current epoch */ |
if( rec_epoch == ssl->in_epoch && |
mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); |
} |
#endif |
/* Drop unexpected ApplicationData records, |
* except at the beginning of renegotiations */ |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && |
ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && |
ssl->state == MBEDTLS_SSL_SERVER_HELLO ) |
#endif |
) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
/* Check length against bounds of the current transform and version */ |
if( ssl->transform_in == NULL ) |
{ |
if( ssl->in_msglen < 1 || |
ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
} |
else |
{ |
if( ssl->in_msglen < ssl->transform_in->minlen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && |
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
/* |
* TLS encrypted messages can have up to 256 bytes of padding |
*/ |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && |
ssl->in_msglen > ssl->transform_in->minlen + |
MBEDTLS_SSL_IN_CONTENT_LEN + 256 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
#endif |
} |
return( 0 ); |
} |
/* |
* If applicable, decrypt (and decompress) record content |
*/ |
static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) |
{ |
int ret, done = 0; |
MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", |
ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ); |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_read != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); |
ret = mbedtls_ssl_hw_record_read( ssl ); |
if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); |
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); |
} |
if( ret == 0 ) |
done = 1; |
} |
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ |
if( !done && ssl->transform_in != NULL ) |
{ |
if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", |
ssl->in_msg, ssl->in_msglen ); |
if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
} |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
if( ssl->transform_in != NULL && |
ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) |
{ |
if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); |
return( ret ); |
} |
} |
#endif /* MBEDTLS_ZLIB_SUPPORT */ |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
mbedtls_ssl_dtls_replay_update( ssl ); |
} |
#endif |
return( 0 ); |
} |
static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); |
/* |
* Read a record. |
* |
* Silently ignore non-fatal alert (and for DTLS, invalid records as well, |
* RFC 6347 4.1.2.7) and continue reading until a valid record is found. |
* |
*/ |
/* Helper functions for mbedtls_ssl_read_record(). */ |
static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); |
static int ssl_get_next_record( mbedtls_ssl_context *ssl ); |
static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); |
int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, |
unsigned update_hs_digest ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); |
if( ssl->keep_current_message == 0 ) |
{ |
do { |
ret = ssl_consume_current_message( ssl ); |
if( ret != 0 ) |
return( ret ); |
if( ssl_record_is_in_progress( ssl ) == 0 ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
int have_buffered = 0; |
/* We only check for buffered messages if the |
* current datagram is fully consumed. */ |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl_next_record_is_in_datagram( ssl ) == 0 ) |
{ |
if( ssl_load_buffered_message( ssl ) == 0 ) |
have_buffered = 1; |
} |
if( have_buffered == 0 ) |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
{ |
ret = ssl_get_next_record( ssl ); |
if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) |
continue; |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); |
return( ret ); |
} |
} |
} |
ret = mbedtls_ssl_handle_message_type( ssl ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) |
{ |
/* Buffer future message */ |
ret = ssl_buffer_message( ssl ); |
if( ret != 0 ) |
return( ret ); |
ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret || |
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); |
if( 0 != ret ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); |
return( ret ); |
} |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && |
update_hs_digest == 1 ) |
{ |
mbedtls_ssl_update_handshake_status( ssl ); |
} |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); |
ssl->keep_current_message = 0; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) |
{ |
if( ssl->in_left > ssl->next_record_offset ) |
return( 1 ); |
return( 0 ); |
} |
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
mbedtls_ssl_hs_buffer * hs_buf; |
int ret = 0; |
if( hs == NULL ) |
return( -1 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); |
if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || |
ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) |
{ |
/* Check if we have seen a ChangeCipherSpec before. |
* If yes, synthesize a CCS record. */ |
if( !hs->buffering.seen_ccs ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); |
ret = -1; |
goto exit; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); |
ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; |
ssl->in_msglen = 1; |
ssl->in_msg[0] = 1; |
/* As long as they are equal, the exact value doesn't matter. */ |
ssl->in_left = 0; |
ssl->next_record_offset = 0; |
hs->buffering.seen_ccs = 0; |
goto exit; |
} |
#if defined(MBEDTLS_DEBUG_C) |
/* Debug only */ |
{ |
unsigned offset; |
for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) |
{ |
hs_buf = &hs->buffering.hs[offset]; |
if( hs_buf->is_valid == 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", |
hs->in_msg_seq + offset, |
hs_buf->is_complete ? "fully" : "partially" ) ); |
} |
} |
} |
#endif /* MBEDTLS_DEBUG_C */ |
/* Check if we have buffered and/or fully reassembled the |
* next handshake message. */ |
hs_buf = &hs->buffering.hs[0]; |
if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) |
{ |
/* Synthesize a record containing the buffered HS message. */ |
size_t msg_len = ( hs_buf->data[1] << 16 ) | |
( hs_buf->data[2] << 8 ) | |
hs_buf->data[3]; |
/* Double-check that we haven't accidentally buffered |
* a message that doesn't fit into the input buffer. */ |
if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", |
hs_buf->data, msg_len + 12 ); |
ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->in_hslen = msg_len + 12; |
ssl->in_msglen = msg_len + 12; |
memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); |
ret = 0; |
goto exit; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", |
hs->in_msg_seq ) ); |
} |
ret = -1; |
exit: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); |
return( ret ); |
} |
static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, |
size_t desired ) |
{ |
int offset; |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", |
(unsigned) desired ) ); |
/* Get rid of future records epoch first, if such exist. */ |
ssl_free_buffered_record( ssl ); |
/* Check if we have enough space available now. */ |
if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - |
hs->buffering.total_bytes_buffered ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); |
return( 0 ); |
} |
/* We don't have enough space to buffer the next expected handshake |
* message. Remove buffers used for future messages to gain space, |
* starting with the most distant one. */ |
for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; |
offset >= 0; offset-- ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", |
offset ) ); |
ssl_buffering_free_slot( ssl, (uint8_t) offset ); |
/* Check if we have enough space available now. */ |
if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - |
hs->buffering.total_bytes_buffered ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); |
return( 0 ); |
} |
} |
return( -1 ); |
} |
static int ssl_buffer_message( mbedtls_ssl_context *ssl ) |
{ |
int ret = 0; |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
if( hs == NULL ) |
return( 0 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); |
switch( ssl->in_msgtype ) |
{ |
case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); |
hs->buffering.seen_ccs = 1; |
break; |
case MBEDTLS_SSL_MSG_HANDSHAKE: |
{ |
unsigned recv_msg_seq_offset; |
unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; |
mbedtls_ssl_hs_buffer *hs_buf; |
size_t msg_len = ssl->in_hslen - 12; |
/* We should never receive an old handshake |
* message - double-check nonetheless. */ |
if( recv_msg_seq < ssl->handshake->in_msg_seq ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; |
if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) |
{ |
/* Silently ignore -- message too far in the future */ |
MBEDTLS_SSL_DEBUG_MSG( 2, |
( "Ignore future HS message with sequence number %u, " |
"buffering window %u - %u", |
recv_msg_seq, ssl->handshake->in_msg_seq, |
ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); |
goto exit; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", |
recv_msg_seq, recv_msg_seq_offset ) ); |
hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; |
/* Check if the buffering for this seq nr has already commenced. */ |
if( !hs_buf->is_valid ) |
{ |
size_t reassembly_buf_sz; |
hs_buf->is_fragmented = |
( ssl_hs_is_proper_fragment( ssl ) == 1 ); |
/* We copy the message back into the input buffer |
* after reassembly, so check that it's not too large. |
* This is an implementation-specific limitation |
* and not one from the standard, hence it is not |
* checked in ssl_check_hs_header(). */ |
if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) |
{ |
/* Ignore message */ |
goto exit; |
} |
/* Check if we have enough space to buffer the message. */ |
if( hs->buffering.total_bytes_buffered > |
MBEDTLS_SSL_DTLS_MAX_BUFFERING ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, |
hs_buf->is_fragmented ); |
if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - |
hs->buffering.total_bytes_buffered ) ) |
{ |
if( recv_msg_seq_offset > 0 ) |
{ |
/* If we can't buffer a future message because |
* of space limitations -- ignore. */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", |
(unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, |
(unsigned) hs->buffering.total_bytes_buffered ) ); |
goto exit; |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n", |
(unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, |
(unsigned) hs->buffering.total_bytes_buffered ) ); |
} |
if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n", |
(unsigned) msg_len, |
(unsigned) reassembly_buf_sz, |
MBEDTLS_SSL_DTLS_MAX_BUFFERING, |
(unsigned) hs->buffering.total_bytes_buffered ) ); |
ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; |
goto exit; |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", |
msg_len ) ); |
hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); |
if( hs_buf->data == NULL ) |
{ |
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; |
goto exit; |
} |
hs_buf->data_len = reassembly_buf_sz; |
/* Prepare final header: copy msg_type, length and message_seq, |
* then add standardised fragment_offset and fragment_length */ |
memcpy( hs_buf->data, ssl->in_msg, 6 ); |
memset( hs_buf->data + 6, 0, 3 ); |
memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); |
hs_buf->is_valid = 1; |
hs->buffering.total_bytes_buffered += reassembly_buf_sz; |
} |
else |
{ |
/* Make sure msg_type and length are consistent */ |
if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); |
/* Ignore */ |
goto exit; |
} |
} |
if( !hs_buf->is_complete ) |
{ |
size_t frag_len, frag_off; |
unsigned char * const msg = hs_buf->data + 12; |
/* |
* Check and copy current fragment |
*/ |
/* Validation of header fields already done in |
* mbedtls_ssl_prepare_handshake_record(). */ |
frag_off = ssl_get_hs_frag_off( ssl ); |
frag_len = ssl_get_hs_frag_len( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", |
frag_off, frag_len ) ); |
memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); |
if( hs_buf->is_fragmented ) |
{ |
unsigned char * const bitmask = msg + msg_len; |
ssl_bitmask_set( bitmask, frag_off, frag_len ); |
hs_buf->is_complete = ( ssl_bitmask_check( bitmask, |
msg_len ) == 0 ); |
} |
else |
{ |
hs_buf->is_complete = 1; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", |
hs_buf->is_complete ? "" : "not yet " ) ); |
} |
break; |
} |
default: |
/* We don't buffer other types of messages. */ |
break; |
} |
exit: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) |
{ |
/* |
* Consume last content-layer message and potentially |
* update in_msglen which keeps track of the contents' |
* consumption state. |
* |
* (1) Handshake messages: |
* Remove last handshake message, move content |
* and adapt in_msglen. |
* |
* (2) Alert messages: |
* Consume whole record content, in_msglen = 0. |
* |
* (3) Change cipher spec: |
* Consume whole record content, in_msglen = 0. |
* |
* (4) Application data: |
* Don't do anything - the record layer provides |
* the application data as a stream transport |
* and consumes through mbedtls_ssl_read only. |
* |
*/ |
/* Case (1): Handshake messages */ |
if( ssl->in_hslen != 0 ) |
{ |
/* Hard assertion to be sure that no application data |
* is in flight, as corrupting ssl->in_msglen during |
* ssl->in_offt != NULL is fatal. */ |
if( ssl->in_offt != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
/* |
* Get next Handshake message in the current record |
*/ |
/* Notes: |
* (1) in_hslen is not necessarily the size of the |
* current handshake content: If DTLS handshake |
* fragmentation is used, that's the fragment |
* size instead. Using the total handshake message |
* size here is faulty and should be changed at |
* some point. |
* (2) While it doesn't seem to cause problems, one |
* has to be very careful not to assume that in_hslen |
* is always <= in_msglen in a sensible communication. |
* Again, it's wrong for DTLS handshake fragmentation. |
* The following check is therefore mandatory, and |
* should not be treated as a silently corrected assertion. |
* Additionally, ssl->in_hslen might be arbitrarily out of |
* bounds after handling a DTLS message with an unexpected |
* sequence number, see mbedtls_ssl_prepare_handshake_record. |
*/ |
if( ssl->in_hslen < ssl->in_msglen ) |
{ |
ssl->in_msglen -= ssl->in_hslen; |
memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, |
ssl->in_msglen ); |
MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", |
ssl->in_msg, ssl->in_msglen ); |
} |
else |
{ |
ssl->in_msglen = 0; |
} |
ssl->in_hslen = 0; |
} |
/* Case (4): Application data */ |
else if( ssl->in_offt != NULL ) |
{ |
return( 0 ); |
} |
/* Everything else (CCS & Alerts) */ |
else |
{ |
ssl->in_msglen = 0; |
} |
return( 0 ); |
} |
static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) |
{ |
if( ssl->in_msglen > 0 ) |
return( 1 ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
if( hs == NULL ) |
return; |
if( hs->buffering.future_record.data != NULL ) |
{ |
hs->buffering.total_bytes_buffered -= |
hs->buffering.future_record.len; |
mbedtls_free( hs->buffering.future_record.data ); |
hs->buffering.future_record.data = NULL; |
} |
} |
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
unsigned char * rec; |
size_t rec_len; |
unsigned rec_epoch; |
if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
return( 0 ); |
if( hs == NULL ) |
return( 0 ); |
rec = hs->buffering.future_record.data; |
rec_len = hs->buffering.future_record.len; |
rec_epoch = hs->buffering.future_record.epoch; |
if( rec == NULL ) |
return( 0 ); |
/* Only consider loading future records if the |
* input buffer is empty. */ |
if( ssl_next_record_is_in_datagram( ssl ) == 1 ) |
return( 0 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); |
if( rec_epoch != ssl->in_epoch ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); |
goto exit; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); |
/* Double-check that the record is not too large */ |
if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN - |
(size_t)( ssl->in_hdr - ssl->in_buf ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
memcpy( ssl->in_hdr, rec, rec_len ); |
ssl->in_left = rec_len; |
ssl->next_record_offset = 0; |
ssl_free_buffered_record( ssl ); |
exit: |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); |
return( 0 ); |
} |
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
size_t const rec_hdr_len = 13; |
size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen; |
/* Don't buffer future records outside handshakes. */ |
if( hs == NULL ) |
return( 0 ); |
/* Only buffer handshake records (we are only interested |
* in Finished messages). */ |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
return( 0 ); |
/* Don't buffer more than one future epoch record. */ |
if( hs->buffering.future_record.data != NULL ) |
return( 0 ); |
/* Don't buffer record if there's not enough buffering space remaining. */ |
if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - |
hs->buffering.total_bytes_buffered ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", |
(unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING, |
(unsigned) hs->buffering.total_bytes_buffered ) ); |
return( 0 ); |
} |
/* Buffer record */ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", |
ssl->in_epoch + 1 ) ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr, |
rec_hdr_len + ssl->in_msglen ); |
/* ssl_parse_record_header() only considers records |
* of the next epoch as candidates for buffering. */ |
hs->buffering.future_record.epoch = ssl->in_epoch + 1; |
hs->buffering.future_record.len = total_buf_sz; |
hs->buffering.future_record.data = |
mbedtls_calloc( 1, hs->buffering.future_record.len ); |
if( hs->buffering.future_record.data == NULL ) |
{ |
/* If we run out of RAM trying to buffer a |
* record from the next epoch, just ignore. */ |
return( 0 ); |
} |
memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz ); |
hs->buffering.total_bytes_buffered += total_buf_sz; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
static int ssl_get_next_record( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
/* We might have buffered a future record; if so, |
* and if the epoch matches now, load it. |
* On success, this call will set ssl->in_left to |
* the length of the buffered record, so that |
* the calls to ssl_fetch_input() below will |
* essentially be no-ops. */ |
ret = ssl_load_buffered_record( ssl ); |
if( ret != 0 ) |
return( ret ); |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); |
return( ret ); |
} |
if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) |
{ |
if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) |
{ |
ret = ssl_buffer_future_record( ssl ); |
if( ret != 0 ) |
return( ret ); |
/* Fall through to handling of unexpected records */ |
ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; |
} |
if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) |
{ |
/* Skip unexpected record (but not whole datagram) */ |
ssl->next_record_offset = ssl->in_msglen |
+ mbedtls_ssl_hdr_len( ssl ); |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " |
"(header)" ) ); |
} |
else |
{ |
/* Skip invalid record and the rest of the datagram */ |
ssl->next_record_offset = 0; |
ssl->in_left = 0; |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " |
"(header)" ) ); |
} |
/* Get next record */ |
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); |
} |
#endif |
return( ret ); |
} |
/* |
* Read and optionally decrypt the message contents |
*/ |
if( ( ret = mbedtls_ssl_fetch_input( ssl, |
mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); |
return( ret ); |
} |
/* Done reading this record, get ready for the next one */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); |
if( ssl->next_record_offset < ssl->in_left ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); |
} |
} |
else |
#endif |
ssl->in_left = 0; |
if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
/* Silently discard invalid records */ |
if( ret == MBEDTLS_ERR_SSL_INVALID_RECORD || |
ret == MBEDTLS_ERR_SSL_INVALID_MAC ) |
{ |
/* Except when waiting for Finished as a bad mac here |
* probably means something went wrong in the handshake |
* (eg wrong psk used, mitm downgrade attempt, etc.) */ |
if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || |
ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) |
{ |
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) |
if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) |
{ |
mbedtls_ssl_send_alert_message( ssl, |
MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); |
} |
#endif |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) |
if( ssl->conf->badmac_limit != 0 && |
++ssl->badmac_seen >= ssl->conf->badmac_limit ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); |
return( MBEDTLS_ERR_SSL_INVALID_MAC ); |
} |
#endif |
/* As above, invalid records cause |
* dismissal of the whole datagram. */ |
ssl->next_record_offset = 0; |
ssl->in_left = 0; |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); |
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); |
} |
return( ret ); |
} |
else |
#endif |
{ |
/* Error out (and send alert) on invalid records */ |
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) |
if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) |
{ |
mbedtls_ssl_send_alert_message( ssl, |
MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); |
} |
#endif |
return( ret ); |
} |
} |
return( 0 ); |
} |
int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
/* |
* Handle particular types of records |
*/ |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) |
{ |
return( ret ); |
} |
} |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) |
{ |
if( ssl->in_msglen != 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d", |
ssl->in_msglen ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
if( ssl->in_msg[0] != 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", |
ssl->in_msg[0] ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && |
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) |
{ |
if( ssl->handshake == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); |
return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); |
} |
#endif |
} |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) |
{ |
if( ssl->in_msglen != 2 ) |
{ |
/* Note: Standard allows for more than one 2 byte alert |
to be packed in a single message, but Mbed TLS doesn't |
currently support this. */ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", |
ssl->in_msglen ) ); |
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", |
ssl->in_msg[0], ssl->in_msg[1] ) ); |
/* |
* Ignore non-fatal alerts, except close_notify and no_renegotiation |
*/ |
if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", |
ssl->in_msg[1] ) ); |
return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); |
} |
if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && |
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); |
return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) |
if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && |
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); |
/* Will be handled when trying to parse ServerHello */ |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && |
ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && |
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); |
/* Will be handled in mbedtls_ssl_parse_certificate() */ |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ |
/* Silently ignore: fetch new message */ |
return MBEDTLS_ERR_SSL_NON_FATAL; |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake != NULL && |
ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) |
{ |
ssl_handshake_wrapup_free_hs_transform( ssl ); |
} |
#endif |
return( 0 ); |
} |
int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
if( ( ret = mbedtls_ssl_send_alert_message( ssl, |
MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, |
unsigned char level, |
unsigned char message ) |
{ |
int ret; |
if( ssl == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); |
ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; |
ssl->out_msglen = 2; |
ssl->out_msg[0] = level; |
ssl->out_msg[1] = message; |
if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); |
return( 0 ); |
} |
/* |
* Handshake functions |
*/ |
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ |
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
/* No certificate support -> dummy functions */ |
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) |
{ |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); |
ssl->state++; |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) |
{ |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); |
ssl->state++; |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
#else |
/* Some certificate support -> implement write and parse */ |
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
size_t i, n; |
const mbedtls_x509_crt *crt; |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); |
ssl->state++; |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_CLI_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) |
{ |
if( ssl->client_auth == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); |
ssl->state++; |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
/* |
* If using SSLv3 and got no cert, send an Alert message |
* (otherwise an empty Certificate message will be sent). |
*/ |
if( mbedtls_ssl_own_cert( ssl ) == NULL && |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
ssl->out_msglen = 2; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; |
ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; |
ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); |
goto write_msg; |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
} |
#endif /* MBEDTLS_SSL_CLI_C */ |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
{ |
if( mbedtls_ssl_own_cert( ssl ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); |
return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); |
} |
} |
#endif |
MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); |
/* |
* 0 . 0 handshake type |
* 1 . 3 handshake length |
* 4 . 6 length of all certs |
* 7 . 9 length of cert. 1 |
* 10 . n-1 peer certificate |
* n . n+2 length of cert. 2 |
* n+3 . ... upper level cert, etc. |
*/ |
i = 7; |
crt = mbedtls_ssl_own_cert( ssl ); |
while( crt != NULL ) |
{ |
n = crt->raw.len; |
if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", |
i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); |
return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); |
} |
ssl->out_msg[i ] = (unsigned char)( n >> 16 ); |
ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); |
ssl->out_msg[i + 2] = (unsigned char)( n ); |
i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); |
i += n; crt = crt->next; |
} |
ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); |
ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); |
ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); |
ssl->out_msglen = i; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; |
#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) |
write_msg: |
#endif |
ssl->state++; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); |
return( ret ); |
} |
/* |
* Once the certificate message is read, parse it into a cert chain and |
* perform basic checks, but leave actual verification to the caller |
*/ |
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
size_t i, n; |
uint8_t alert; |
#if defined(MBEDTLS_SSL_SRV_C) |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
/* |
* Check if the client sent an empty certificate |
*/ |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
if( ssl->in_msglen == 2 && |
ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && |
ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && |
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); |
/* The client was asked for a certificate but didn't send |
one. The client should know what's going on, so we |
don't send an alert. */ |
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; |
return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && |
ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && |
ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && |
memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); |
/* The client was asked for a certificate but didn't send |
one. The client should know what's going on, so we |
don't send an alert. */ |
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; |
return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
#endif /* MBEDTLS_SSL_SRV_C */ |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || |
ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
i = mbedtls_ssl_hs_hdr_len( ssl ); |
/* |
* Same message structure as in mbedtls_ssl_write_certificate() |
*/ |
n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; |
if( ssl->in_msg[i] != 0 || |
ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
/* In case we tried to reuse a session but it failed */ |
if( ssl->session_negotiate->peer_cert != NULL ) |
{ |
mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); |
mbedtls_free( ssl->session_negotiate->peer_cert ); |
} |
if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, |
sizeof( mbedtls_x509_crt ) ) ) == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", |
sizeof( mbedtls_x509_crt ) ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); |
i += 3; |
while( i < ssl->in_hslen ) |
{ |
if ( i + 3 > ssl->in_hslen ) { |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
if( ssl->in_msg[i] != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) |
| (unsigned int) ssl->in_msg[i + 2]; |
i += 3; |
if( n < 128 || i + n > ssl->in_hslen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, |
ssl->in_msg + i, n ); |
switch( ret ) |
{ |
case 0: /*ok*/ |
case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: |
/* Ignore certificate with an unknown algorithm: maybe a |
prior certificate was already trusted. */ |
break; |
case MBEDTLS_ERR_X509_ALLOC_FAILED: |
alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; |
goto crt_parse_der_failed; |
case MBEDTLS_ERR_X509_UNKNOWN_VERSION: |
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; |
goto crt_parse_der_failed; |
default: |
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; |
crt_parse_der_failed: |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); |
MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); |
return( ret ); |
} |
i += n; |
} |
MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); |
/* |
* On client, make sure the server cert doesn't change during renego to |
* avoid "triple handshake" attack: https://secure-resumption.com/ |
*/ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && |
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
{ |
if( ssl->session->peer_cert == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
if( ssl->session->peer_cert->raw.len != |
ssl->session_negotiate->peer_cert->raw.len || |
memcmp( ssl->session->peer_cert->raw.p, |
ssl->session_negotiate->peer_cert->raw.p, |
ssl->session->peer_cert->raw.len ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); |
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); |
} |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ |
return( 0 ); |
} |
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = |
ssl->transform_negotiate->ciphersuite_info; |
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET |
? ssl->handshake->sni_authmode |
: ssl->conf->authmode; |
#else |
const int authmode = ssl->conf->authmode; |
#endif |
void *rs_ctx = NULL; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); |
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); |
ssl->state++; |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); |
ssl->state++; |
return( 0 ); |
} |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
authmode == MBEDTLS_SSL_VERIFY_NONE ) |
{ |
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); |
ssl->state++; |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled && |
ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) |
{ |
goto crt_verify; |
} |
#endif |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
/* mbedtls_ssl_read_record may have sent an alert already. We |
let it decide whether to alert. */ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 ) |
{ |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE && |
authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) |
{ |
ret = 0; |
} |
#endif |
ssl->state++; |
return( ret ); |
} |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ssl->handshake->ecrs_enabled) |
ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; |
crt_verify: |
if( ssl->handshake->ecrs_enabled) |
rs_ctx = &ssl->handshake->ecrs_ctx; |
#endif |
if( authmode != MBEDTLS_SSL_VERIFY_NONE ) |
{ |
mbedtls_x509_crt *ca_chain; |
mbedtls_x509_crl *ca_crl; |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
if( ssl->handshake->sni_ca_chain != NULL ) |
{ |
ca_chain = ssl->handshake->sni_ca_chain; |
ca_crl = ssl->handshake->sni_ca_crl; |
} |
else |
#endif |
{ |
ca_chain = ssl->conf->ca_chain; |
ca_crl = ssl->conf->ca_crl; |
} |
/* |
* Main check: verify certificate |
*/ |
ret = mbedtls_x509_crt_verify_restartable( |
ssl->session_negotiate->peer_cert, |
ca_chain, ca_crl, |
ssl->conf->cert_profile, |
ssl->hostname, |
&ssl->session_negotiate->verify_result, |
ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx ); |
if( ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); |
} |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); |
#endif |
/* |
* Secondary checks: always done, but change 'ret' only if it was 0 |
*/ |
#if defined(MBEDTLS_ECP_C) |
{ |
const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; |
/* If certificate uses an EC key, make sure the curve is OK */ |
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && |
mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) |
{ |
ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); |
if( ret == 0 ) |
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; |
} |
} |
#endif /* MBEDTLS_ECP_C */ |
if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, |
ciphersuite_info, |
! ssl->conf->endpoint, |
&ssl->session_negotiate->verify_result ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); |
if( ret == 0 ) |
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; |
} |
/* mbedtls_x509_crt_verify_with_profile is supposed to report a |
* verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, |
* with details encoded in the verification flags. All other kinds |
* of error codes, including those from the user provided f_vrfy |
* functions, are treated as fatal and lead to a failure of |
* ssl_parse_certificate even if verification was optional. */ |
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && |
( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || |
ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) |
{ |
ret = 0; |
} |
if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); |
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; |
} |
if( ret != 0 ) |
{ |
uint8_t alert; |
/* The certificate may have been rejected for several reasons. |
Pick one and send the corresponding alert. Which alert to send |
may be a subject of debate in some cases. */ |
if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) |
alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) |
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) |
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) |
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) |
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) |
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) |
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) |
alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) |
alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; |
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) |
alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; |
else |
alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
alert ); |
} |
#if defined(MBEDTLS_DEBUG_C) |
if( ssl->session_negotiate->verify_result != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x", |
ssl->session_negotiate->verify_result ) ); |
} |
else |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); |
} |
#endif /* MBEDTLS_DEBUG_C */ |
} |
ssl->state++; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); |
return( ret ); |
} |
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED |
!MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED |
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED |
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED |
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED |
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED |
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); |
ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; |
ssl->out_msglen = 1; |
ssl->out_msg[0] = 1; |
ssl->state++; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); |
return( 0 ); |
} |
int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
/* CCS records are only accepted if they have length 1 and content '1', |
* so we don't need to check this here. */ |
/* |
* Switch to our negotiated transform and session parameters for inbound |
* data. |
*/ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); |
ssl->transform_in = ssl->transform_negotiate; |
ssl->session_in = ssl->session_negotiate; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
ssl_dtls_replay_reset( ssl ); |
#endif |
/* Increment epoch */ |
if( ++ssl->in_epoch == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); |
/* This is highly unlikely to happen for legitimate reasons, so |
treat it as an attack and don't send an alert. */ |
return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
memset( ssl->in_ctr, 0, 8 ); |
ssl_update_in_pointers( ssl, ssl->transform_negotiate ); |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_activate != NULL ) |
{ |
if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); |
} |
} |
#endif |
ssl->state++; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); |
return( 0 ); |
} |
void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, |
const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) |
{ |
((void) ciphersuite_info); |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) |
ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; |
else |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA512_C) |
if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) |
ssl->handshake->update_checksum = ssl_update_checksum_sha384; |
else |
#endif |
#if defined(MBEDTLS_SHA256_C) |
if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) |
ssl->handshake->update_checksum = ssl_update_checksum_sha256; |
else |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return; |
} |
} |
void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
mbedtls_md5_starts_ret( &ssl->handshake->fin_md5 ); |
mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 ); |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
} |
static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); |
mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); |
mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); |
} |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); |
} |
#endif |
#if defined(MBEDTLS_SHA512_C) |
static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); |
} |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
static void ssl_calc_finished_ssl( |
mbedtls_ssl_context *ssl, unsigned char *buf, int from ) |
{ |
const char *sender; |
mbedtls_md5_context md5; |
mbedtls_sha1_context sha1; |
unsigned char padbuf[48]; |
unsigned char md5sum[16]; |
unsigned char sha1sum[20]; |
mbedtls_ssl_session *session = ssl->session_negotiate; |
if( !session ) |
session = ssl->session; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); |
mbedtls_md5_init( &md5 ); |
mbedtls_sha1_init( &sha1 ); |
mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); |
mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); |
/* |
* SSLv3: |
* hash = |
* MD5( master + pad2 + |
* MD5( handshake + sender + master + pad1 ) ) |
* + SHA1( master + pad2 + |
* SHA1( handshake + sender + master + pad1 ) ) |
*/ |
#if !defined(MBEDTLS_MD5_ALT) |
MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) |
md5.state, sizeof( md5.state ) ); |
#endif |
#if !defined(MBEDTLS_SHA1_ALT) |
MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) |
sha1.state, sizeof( sha1.state ) ); |
#endif |
sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" |
: "SRVR"; |
memset( padbuf, 0x36, 48 ); |
mbedtls_md5_update_ret( &md5, (const unsigned char *) sender, 4 ); |
mbedtls_md5_update_ret( &md5, session->master, 48 ); |
mbedtls_md5_update_ret( &md5, padbuf, 48 ); |
mbedtls_md5_finish_ret( &md5, md5sum ); |
mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 ); |
mbedtls_sha1_update_ret( &sha1, session->master, 48 ); |
mbedtls_sha1_update_ret( &sha1, padbuf, 40 ); |
mbedtls_sha1_finish_ret( &sha1, sha1sum ); |
memset( padbuf, 0x5C, 48 ); |
mbedtls_md5_starts_ret( &md5 ); |
mbedtls_md5_update_ret( &md5, session->master, 48 ); |
mbedtls_md5_update_ret( &md5, padbuf, 48 ); |
mbedtls_md5_update_ret( &md5, md5sum, 16 ); |
mbedtls_md5_finish_ret( &md5, buf ); |
mbedtls_sha1_starts_ret( &sha1 ); |
mbedtls_sha1_update_ret( &sha1, session->master, 48 ); |
mbedtls_sha1_update_ret( &sha1, padbuf , 40 ); |
mbedtls_sha1_update_ret( &sha1, sha1sum, 20 ); |
mbedtls_sha1_finish_ret( &sha1, buf + 16 ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); |
mbedtls_md5_free( &md5 ); |
mbedtls_sha1_free( &sha1 ); |
mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); |
mbedtls_platform_zeroize( md5sum, sizeof( md5sum ) ); |
mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) |
static void ssl_calc_finished_tls( |
mbedtls_ssl_context *ssl, unsigned char *buf, int from ) |
{ |
int len = 12; |
const char *sender; |
mbedtls_md5_context md5; |
mbedtls_sha1_context sha1; |
unsigned char padbuf[36]; |
mbedtls_ssl_session *session = ssl->session_negotiate; |
if( !session ) |
session = ssl->session; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); |
mbedtls_md5_init( &md5 ); |
mbedtls_sha1_init( &sha1 ); |
mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); |
mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); |
/* |
* TLSv1: |
* hash = PRF( master, finished_label, |
* MD5( handshake ) + SHA1( handshake ) )[0..11] |
*/ |
#if !defined(MBEDTLS_MD5_ALT) |
MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) |
md5.state, sizeof( md5.state ) ); |
#endif |
#if !defined(MBEDTLS_SHA1_ALT) |
MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) |
sha1.state, sizeof( sha1.state ) ); |
#endif |
sender = ( from == MBEDTLS_SSL_IS_CLIENT ) |
? "client finished" |
: "server finished"; |
mbedtls_md5_finish_ret( &md5, padbuf ); |
mbedtls_sha1_finish_ret( &sha1, padbuf + 16 ); |
ssl->handshake->tls_prf( session->master, 48, sender, |
padbuf, 36, buf, len ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); |
mbedtls_md5_free( &md5 ); |
mbedtls_sha1_free( &sha1 ); |
mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
static void ssl_calc_finished_tls_sha256( |
mbedtls_ssl_context *ssl, unsigned char *buf, int from ) |
{ |
int len = 12; |
const char *sender; |
mbedtls_sha256_context sha256; |
unsigned char padbuf[32]; |
mbedtls_ssl_session *session = ssl->session_negotiate; |
if( !session ) |
session = ssl->session; |
mbedtls_sha256_init( &sha256 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); |
mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); |
/* |
* TLSv1.2: |
* hash = PRF( master, finished_label, |
* Hash( handshake ) )[0.11] |
*/ |
#if !defined(MBEDTLS_SHA256_ALT) |
MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) |
sha256.state, sizeof( sha256.state ) ); |
#endif |
sender = ( from == MBEDTLS_SSL_IS_CLIENT ) |
? "client finished" |
: "server finished"; |
mbedtls_sha256_finish_ret( &sha256, padbuf ); |
ssl->handshake->tls_prf( session->master, 48, sender, |
padbuf, 32, buf, len ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); |
mbedtls_sha256_free( &sha256 ); |
mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); |
} |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
static void ssl_calc_finished_tls_sha384( |
mbedtls_ssl_context *ssl, unsigned char *buf, int from ) |
{ |
int len = 12; |
const char *sender; |
mbedtls_sha512_context sha512; |
unsigned char padbuf[48]; |
mbedtls_ssl_session *session = ssl->session_negotiate; |
if( !session ) |
session = ssl->session; |
mbedtls_sha512_init( &sha512 ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); |
mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); |
/* |
* TLSv1.2: |
* hash = PRF( master, finished_label, |
* Hash( handshake ) )[0.11] |
*/ |
#if !defined(MBEDTLS_SHA512_ALT) |
MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) |
sha512.state, sizeof( sha512.state ) ); |
#endif |
sender = ( from == MBEDTLS_SSL_IS_CLIENT ) |
? "client finished" |
: "server finished"; |
mbedtls_sha512_finish_ret( &sha512, padbuf ); |
ssl->handshake->tls_prf( session->master, 48, sender, |
padbuf, 48, buf, len ); |
MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); |
mbedtls_sha512_free( &sha512 ); |
mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); |
} |
#endif /* MBEDTLS_SHA512_C */ |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); |
/* |
* Free our handshake params |
*/ |
mbedtls_ssl_handshake_free( ssl ); |
mbedtls_free( ssl->handshake ); |
ssl->handshake = NULL; |
/* |
* Free the previous transform and swith in the current one |
*/ |
if( ssl->transform ) |
{ |
mbedtls_ssl_transform_free( ssl->transform ); |
mbedtls_free( ssl->transform ); |
} |
ssl->transform = ssl->transform_negotiate; |
ssl->transform_negotiate = NULL; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); |
} |
void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) |
{ |
int resume = ssl->handshake->resume; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
{ |
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; |
ssl->renego_records_seen = 0; |
} |
#endif |
/* |
* Free the previous session and switch in the current one |
*/ |
if( ssl->session ) |
{ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
/* RFC 7366 3.1: keep the EtM state */ |
ssl->session_negotiate->encrypt_then_mac = |
ssl->session->encrypt_then_mac; |
#endif |
mbedtls_ssl_session_free( ssl->session ); |
mbedtls_free( ssl->session ); |
} |
ssl->session = ssl->session_negotiate; |
ssl->session_negotiate = NULL; |
/* |
* Add cache entry |
*/ |
if( ssl->conf->f_set_cache != NULL && |
ssl->session->id_len != 0 && |
resume == 0 ) |
{ |
if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->handshake->flight != NULL ) |
{ |
/* Cancel handshake timer */ |
ssl_set_timer( ssl, 0 ); |
/* Keep last flight around in case we need to resend it: |
* we need the handshake and transform structures for that */ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); |
} |
else |
#endif |
ssl_handshake_wrapup_free_hs_transform( ssl ); |
ssl->state++; |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); |
} |
int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) |
{ |
int ret, hash_len; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); |
ssl_update_out_pointers( ssl, ssl->transform_negotiate ); |
ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); |
/* |
* RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites |
* may define some other value. Currently (early 2016), no defined |
* ciphersuite does this (and this is unlikely to change as activity has |
* moved to TLS 1.3 now) so we can keep the hardcoded 12 here. |
*/ |
hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ssl->verify_data_len = hash_len; |
memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); |
#endif |
ssl->out_msglen = 4 + hash_len; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; |
/* |
* In case of session resuming, invert the client and server |
* ChangeCipherSpec messages order. |
*/ |
if( ssl->handshake->resume != 0 ) |
{ |
#if defined(MBEDTLS_SSL_CLI_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) |
ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; |
#endif |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; |
#endif |
} |
else |
ssl->state++; |
/* |
* Switch to our negotiated transform and session parameters for outbound |
* data. |
*/ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
unsigned char i; |
/* Remember current epoch settings for resending */ |
ssl->handshake->alt_transform_out = ssl->transform_out; |
memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 ); |
/* Set sequence_number to zero */ |
memset( ssl->cur_out_ctr + 2, 0, 6 ); |
/* Increment epoch */ |
for( i = 2; i > 0; i-- ) |
if( ++ssl->cur_out_ctr[i - 1] != 0 ) |
break; |
/* The loop goes to its end iff the counter is wrapping */ |
if( i == 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); |
return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
memset( ssl->cur_out_ctr, 0, 8 ); |
ssl->transform_out = ssl->transform_negotiate; |
ssl->session_out = ssl->session_negotiate; |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_activate != NULL ) |
{ |
if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); |
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); |
} |
} |
#endif |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
mbedtls_ssl_send_flight_completed( ssl ); |
#endif |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); |
return( ret ); |
} |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
#define SSL_MAX_HASH_LEN 36 |
#else |
#define SSL_MAX_HASH_LEN 12 |
#endif |
int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
unsigned int hash_len; |
unsigned char buf[SSL_MAX_HASH_LEN]; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); |
ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
/* There is currently no ciphersuite using another length with TLS 1.2 */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
hash_len = 36; |
else |
#endif |
hash_len = 12; |
if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || |
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); |
} |
if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), |
buf, hash_len ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); |
return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ssl->verify_data_len = hash_len; |
memcpy( ssl->peer_verify_data, buf, hash_len ); |
#endif |
if( ssl->handshake->resume != 0 ) |
{ |
#if defined(MBEDTLS_SSL_CLI_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) |
ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; |
#endif |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; |
#endif |
} |
else |
ssl->state++; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
mbedtls_ssl_recv_flight_completed( ssl ); |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); |
return( 0 ); |
} |
static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) |
{ |
memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
mbedtls_md5_init( &handshake->fin_md5 ); |
mbedtls_sha1_init( &handshake->fin_sha1 ); |
mbedtls_md5_starts_ret( &handshake->fin_md5 ); |
mbedtls_sha1_starts_ret( &handshake->fin_sha1 ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
mbedtls_sha256_init( &handshake->fin_sha256 ); |
mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
mbedtls_sha512_init( &handshake->fin_sha512 ); |
mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 ); |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
handshake->update_checksum = ssl_update_checksum_start; |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); |
#endif |
#if defined(MBEDTLS_DHM_C) |
mbedtls_dhm_init( &handshake->dhm_ctx ); |
#endif |
#if defined(MBEDTLS_ECDH_C) |
mbedtls_ecdh_init( &handshake->ecdh_ctx ); |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); |
#if defined(MBEDTLS_SSL_CLI_C) |
handshake->ecjpake_cache = NULL; |
handshake->ecjpake_cache_len = 0; |
#endif |
#endif |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); |
#endif |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; |
#endif |
} |
static void ssl_transform_init( mbedtls_ssl_transform *transform ) |
{ |
memset( transform, 0, sizeof(mbedtls_ssl_transform) ); |
mbedtls_cipher_init( &transform->cipher_ctx_enc ); |
mbedtls_cipher_init( &transform->cipher_ctx_dec ); |
mbedtls_md_init( &transform->md_ctx_enc ); |
mbedtls_md_init( &transform->md_ctx_dec ); |
} |
void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) |
{ |
memset( session, 0, sizeof(mbedtls_ssl_session) ); |
} |
static int ssl_handshake_init( mbedtls_ssl_context *ssl ) |
{ |
/* Clear old handshake information if present */ |
if( ssl->transform_negotiate ) |
mbedtls_ssl_transform_free( ssl->transform_negotiate ); |
if( ssl->session_negotiate ) |
mbedtls_ssl_session_free( ssl->session_negotiate ); |
if( ssl->handshake ) |
mbedtls_ssl_handshake_free( ssl ); |
/* |
* Either the pointers are now NULL or cleared properly and can be freed. |
* Now allocate missing structures. |
*/ |
if( ssl->transform_negotiate == NULL ) |
{ |
ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); |
} |
if( ssl->session_negotiate == NULL ) |
{ |
ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); |
} |
if( ssl->handshake == NULL ) |
{ |
ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); |
} |
/* All pointers should exist and can be directly freed without issue */ |
if( ssl->handshake == NULL || |
ssl->transform_negotiate == NULL || |
ssl->session_negotiate == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); |
mbedtls_free( ssl->handshake ); |
mbedtls_free( ssl->transform_negotiate ); |
mbedtls_free( ssl->session_negotiate ); |
ssl->handshake = NULL; |
ssl->transform_negotiate = NULL; |
ssl->session_negotiate = NULL; |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
/* Initialize structures */ |
mbedtls_ssl_session_init( ssl->session_negotiate ); |
ssl_transform_init( ssl->transform_negotiate ); |
ssl_handshake_params_init( ssl->handshake ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
ssl->handshake->alt_transform_out = ssl->transform_out; |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; |
else |
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; |
ssl_set_timer( ssl, 0 ); |
} |
#endif |
return( 0 ); |
} |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) |
/* Dummy cookie callbacks for defaults */ |
static int ssl_cookie_write_dummy( void *ctx, |
unsigned char **p, unsigned char *end, |
const unsigned char *cli_id, size_t cli_id_len ) |
{ |
((void) ctx); |
((void) p); |
((void) end); |
((void) cli_id); |
((void) cli_id_len); |
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); |
} |
static int ssl_cookie_check_dummy( void *ctx, |
const unsigned char *cookie, size_t cookie_len, |
const unsigned char *cli_id, size_t cli_id_len ) |
{ |
((void) ctx); |
((void) cookie); |
((void) cookie_len); |
((void) cli_id); |
((void) cli_id_len); |
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); |
} |
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ |
/* Once ssl->out_hdr as the address of the beginning of the |
* next outgoing record is set, deduce the other pointers. |
* |
* Note: For TLS, we save the implicit record sequence number |
* (entering MAC computation) in the 8 bytes before ssl->out_hdr, |
* and the caller has to make sure there's space for this. |
*/ |
static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, |
mbedtls_ssl_transform *transform ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
ssl->out_ctr = ssl->out_hdr + 3; |
ssl->out_len = ssl->out_hdr + 11; |
ssl->out_iv = ssl->out_hdr + 13; |
} |
else |
#endif |
{ |
ssl->out_ctr = ssl->out_hdr - 8; |
ssl->out_len = ssl->out_hdr + 3; |
ssl->out_iv = ssl->out_hdr + 5; |
} |
/* Adjust out_msg to make space for explicit IV, if used. */ |
if( transform != NULL && |
ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) |
{ |
ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen; |
} |
else |
ssl->out_msg = ssl->out_iv; |
} |
/* Once ssl->in_hdr as the address of the beginning of the |
* next incoming record is set, deduce the other pointers. |
* |
* Note: For TLS, we save the implicit record sequence number |
* (entering MAC computation) in the 8 bytes before ssl->in_hdr, |
* and the caller has to make sure there's space for this. |
*/ |
static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, |
mbedtls_ssl_transform *transform ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
ssl->in_ctr = ssl->in_hdr + 3; |
ssl->in_len = ssl->in_hdr + 11; |
ssl->in_iv = ssl->in_hdr + 13; |
} |
else |
#endif |
{ |
ssl->in_ctr = ssl->in_hdr - 8; |
ssl->in_len = ssl->in_hdr + 3; |
ssl->in_iv = ssl->in_hdr + 5; |
} |
/* Offset in_msg from in_iv to allow space for explicit IV, if used. */ |
if( transform != NULL && |
ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) |
{ |
ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen; |
} |
else |
ssl->in_msg = ssl->in_iv; |
} |
/* |
* Initialize an SSL context |
*/ |
void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) |
{ |
memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); |
} |
/* |
* Setup an SSL context |
*/ |
static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) |
{ |
/* Set the incoming and outgoing record pointers. */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
ssl->out_hdr = ssl->out_buf; |
ssl->in_hdr = ssl->in_buf; |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
{ |
ssl->out_hdr = ssl->out_buf + 8; |
ssl->in_hdr = ssl->in_buf + 8; |
} |
/* Derive other internal pointers. */ |
ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); |
ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ ); |
} |
int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, |
const mbedtls_ssl_config *conf ) |
{ |
int ret; |
ssl->conf = conf; |
/* |
* Prepare base structures |
*/ |
/* Set to NULL in case of an error condition */ |
ssl->out_buf = NULL; |
ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN ); |
if( ssl->in_buf == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) ); |
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; |
goto error; |
} |
ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN ); |
if( ssl->out_buf == NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) ); |
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; |
goto error; |
} |
ssl_reset_in_out_pointers( ssl ); |
if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) |
goto error; |
return( 0 ); |
error: |
mbedtls_free( ssl->in_buf ); |
mbedtls_free( ssl->out_buf ); |
ssl->conf = NULL; |
ssl->in_buf = NULL; |
ssl->out_buf = NULL; |
ssl->in_hdr = NULL; |
ssl->in_ctr = NULL; |
ssl->in_len = NULL; |
ssl->in_iv = NULL; |
ssl->in_msg = NULL; |
ssl->out_hdr = NULL; |
ssl->out_ctr = NULL; |
ssl->out_len = NULL; |
ssl->out_iv = NULL; |
ssl->out_msg = NULL; |
return( ret ); |
} |
/* |
* Reset an initialized and used SSL context for re-use while retaining |
* all application-set variables, function pointers and data. |
* |
* If partial is non-zero, keep data in the input buffer and client ID. |
* (Use when a DTLS client reconnects from the same port.) |
*/ |
static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) |
{ |
int ret; |
#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ |
!defined(MBEDTLS_SSL_SRV_C) |
((void) partial); |
#endif |
ssl->state = MBEDTLS_SSL_HELLO_REQUEST; |
/* Cancel any possibly running timer */ |
ssl_set_timer( ssl, 0 ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; |
ssl->renego_records_seen = 0; |
ssl->verify_data_len = 0; |
memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); |
memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); |
#endif |
ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; |
ssl->in_offt = NULL; |
ssl_reset_in_out_pointers( ssl ); |
ssl->in_msgtype = 0; |
ssl->in_msglen = 0; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
ssl->next_record_offset = 0; |
ssl->in_epoch = 0; |
#endif |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
ssl_dtls_replay_reset( ssl ); |
#endif |
ssl->in_hslen = 0; |
ssl->nb_zero = 0; |
ssl->keep_current_message = 0; |
ssl->out_msgtype = 0; |
ssl->out_msglen = 0; |
ssl->out_left = 0; |
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) |
if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) |
ssl->split_done = 0; |
#endif |
memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); |
ssl->transform_in = NULL; |
ssl->transform_out = NULL; |
ssl->session_in = NULL; |
ssl->session_out = NULL; |
memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); |
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) |
if( partial == 0 ) |
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ |
{ |
ssl->in_left = 0; |
memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); |
} |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_reset != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); |
if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); |
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); |
} |
} |
#endif |
if( ssl->transform ) |
{ |
mbedtls_ssl_transform_free( ssl->transform ); |
mbedtls_free( ssl->transform ); |
ssl->transform = NULL; |
} |
if( ssl->session ) |
{ |
mbedtls_ssl_session_free( ssl->session ); |
mbedtls_free( ssl->session ); |
ssl->session = NULL; |
} |
#if defined(MBEDTLS_SSL_ALPN) |
ssl->alpn_chosen = NULL; |
#endif |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) |
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) |
if( partial == 0 ) |
#endif |
{ |
mbedtls_free( ssl->cli_id ); |
ssl->cli_id = NULL; |
ssl->cli_id_len = 0; |
} |
#endif |
if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
/* |
* Reset an initialized and used SSL context for re-use while retaining |
* all application-set variables, function pointers and data. |
*/ |
int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) |
{ |
return( ssl_session_reset_int( ssl, 0 ) ); |
} |
/* |
* SSL set accessors |
*/ |
void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) |
{ |
conf->endpoint = endpoint; |
} |
void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) |
{ |
conf->transport = transport; |
} |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) |
{ |
conf->anti_replay = mode; |
} |
#endif |
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) |
void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) |
{ |
conf->badmac_limit = limit; |
} |
#endif |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, |
unsigned allow_packing ) |
{ |
ssl->disable_datagram_packing = !allow_packing; |
} |
void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, |
uint32_t min, uint32_t max ) |
{ |
conf->hs_timeout_min = min; |
conf->hs_timeout_max = max; |
} |
#endif |
void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) |
{ |
conf->authmode = authmode; |
} |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, |
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), |
void *p_vrfy ) |
{ |
conf->f_vrfy = f_vrfy; |
conf->p_vrfy = p_vrfy; |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
conf->f_rng = f_rng; |
conf->p_rng = p_rng; |
} |
void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, |
void (*f_dbg)(void *, int, const char *, int, const char *), |
void *p_dbg ) |
{ |
conf->f_dbg = f_dbg; |
conf->p_dbg = p_dbg; |
} |
void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, |
void *p_bio, |
mbedtls_ssl_send_t *f_send, |
mbedtls_ssl_recv_t *f_recv, |
mbedtls_ssl_recv_timeout_t *f_recv_timeout ) |
{ |
ssl->p_bio = p_bio; |
ssl->f_send = f_send; |
ssl->f_recv = f_recv; |
ssl->f_recv_timeout = f_recv_timeout; |
} |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ) |
{ |
ssl->mtu = mtu; |
} |
#endif |
void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) |
{ |
conf->read_timeout = timeout; |
} |
void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, |
void *p_timer, |
mbedtls_ssl_set_timer_t *f_set_timer, |
mbedtls_ssl_get_timer_t *f_get_timer ) |
{ |
ssl->p_timer = p_timer; |
ssl->f_set_timer = f_set_timer; |
ssl->f_get_timer = f_get_timer; |
/* Make sure we start with no timer running */ |
ssl_set_timer( ssl, 0 ); |
} |
#if defined(MBEDTLS_SSL_SRV_C) |
void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, |
void *p_cache, |
int (*f_get_cache)(void *, mbedtls_ssl_session *), |
int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) |
{ |
conf->p_cache = p_cache; |
conf->f_get_cache = f_get_cache; |
conf->f_set_cache = f_set_cache; |
} |
#endif /* MBEDTLS_SSL_SRV_C */ |
#if defined(MBEDTLS_SSL_CLI_C) |
int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) |
{ |
int ret; |
if( ssl == NULL || |
session == NULL || |
ssl->session_negotiate == NULL || |
ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) |
{ |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) |
return( ret ); |
ssl->handshake->resume = 1; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_CLI_C */ |
void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, |
const int *ciphersuites ) |
{ |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; |
} |
void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, |
const int *ciphersuites, |
int major, int minor ) |
{ |
if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) |
return; |
if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) |
return; |
conf->ciphersuite_list[minor] = ciphersuites; |
} |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, |
const mbedtls_x509_crt_profile *profile ) |
{ |
conf->cert_profile = profile; |
} |
/* Append a new keycert entry to a (possibly empty) list */ |
static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, |
mbedtls_x509_crt *cert, |
mbedtls_pk_context *key ) |
{ |
mbedtls_ssl_key_cert *new_cert; |
new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); |
if( new_cert == NULL ) |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
new_cert->cert = cert; |
new_cert->key = key; |
new_cert->next = NULL; |
/* Update head is the list was null, else add to the end */ |
if( *head == NULL ) |
{ |
*head = new_cert; |
} |
else |
{ |
mbedtls_ssl_key_cert *cur = *head; |
while( cur->next != NULL ) |
cur = cur->next; |
cur->next = new_cert; |
} |
return( 0 ); |
} |
int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, |
mbedtls_x509_crt *own_cert, |
mbedtls_pk_context *pk_key ) |
{ |
return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); |
} |
void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, |
mbedtls_x509_crt *ca_chain, |
mbedtls_x509_crl *ca_crl ) |
{ |
conf->ca_chain = ca_chain; |
conf->ca_crl = ca_crl; |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, |
mbedtls_x509_crt *own_cert, |
mbedtls_pk_context *pk_key ) |
{ |
return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, |
own_cert, pk_key ) ); |
} |
void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, |
mbedtls_x509_crt *ca_chain, |
mbedtls_x509_crl *ca_crl ) |
{ |
ssl->handshake->sni_ca_chain = ca_chain; |
ssl->handshake->sni_ca_crl = ca_crl; |
} |
void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, |
int authmode ) |
{ |
ssl->handshake->sni_authmode = authmode; |
} |
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
/* |
* Set EC J-PAKE password for current handshake |
*/ |
int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, |
const unsigned char *pw, |
size_t pw_len ) |
{ |
mbedtls_ecjpake_role role; |
if( ssl->handshake == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
role = MBEDTLS_ECJPAKE_SERVER; |
else |
role = MBEDTLS_ECJPAKE_CLIENT; |
return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, |
role, |
MBEDTLS_MD_SHA256, |
MBEDTLS_ECP_DP_SECP256R1, |
pw, pw_len ) ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, |
const unsigned char *psk, size_t psk_len, |
const unsigned char *psk_identity, size_t psk_identity_len ) |
{ |
if( psk == NULL || psk_identity == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( psk_len > MBEDTLS_PSK_MAX_LEN ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
/* Identity len will be encoded on two bytes */ |
if( ( psk_identity_len >> 16 ) != 0 || |
psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) |
{ |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
if( conf->psk != NULL ) |
{ |
mbedtls_platform_zeroize( conf->psk, conf->psk_len ); |
mbedtls_free( conf->psk ); |
conf->psk = NULL; |
conf->psk_len = 0; |
} |
if( conf->psk_identity != NULL ) |
{ |
mbedtls_free( conf->psk_identity ); |
conf->psk_identity = NULL; |
conf->psk_identity_len = 0; |
} |
if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || |
( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) |
{ |
mbedtls_free( conf->psk ); |
mbedtls_free( conf->psk_identity ); |
conf->psk = NULL; |
conf->psk_identity = NULL; |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
} |
conf->psk_len = psk_len; |
conf->psk_identity_len = psk_identity_len; |
memcpy( conf->psk, psk, conf->psk_len ); |
memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); |
return( 0 ); |
} |
int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, |
const unsigned char *psk, size_t psk_len ) |
{ |
if( psk == NULL || ssl->handshake == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( psk_len > MBEDTLS_PSK_MAX_LEN ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( ssl->handshake->psk != NULL ) |
{ |
mbedtls_platform_zeroize( ssl->handshake->psk, |
ssl->handshake->psk_len ); |
mbedtls_free( ssl->handshake->psk ); |
ssl->handshake->psk_len = 0; |
} |
if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
ssl->handshake->psk_len = psk_len; |
memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); |
return( 0 ); |
} |
void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, |
int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, |
size_t), |
void *p_psk ) |
{ |
conf->f_psk = f_psk; |
conf->p_psk = p_psk; |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ |
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) |
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) |
{ |
int ret; |
if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || |
( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) |
{ |
mbedtls_mpi_free( &conf->dhm_P ); |
mbedtls_mpi_free( &conf->dhm_G ); |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_DEPRECATED_REMOVED */ |
int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, |
const unsigned char *dhm_P, size_t P_len, |
const unsigned char *dhm_G, size_t G_len ) |
{ |
int ret; |
if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || |
( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) |
{ |
mbedtls_mpi_free( &conf->dhm_P ); |
mbedtls_mpi_free( &conf->dhm_G ); |
return( ret ); |
} |
return( 0 ); |
} |
int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) |
{ |
int ret; |
if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || |
( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) |
{ |
mbedtls_mpi_free( &conf->dhm_P ); |
mbedtls_mpi_free( &conf->dhm_G ); |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ |
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) |
/* |
* Set the minimum length for Diffie-Hellman parameters |
*/ |
void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, |
unsigned int bitlen ) |
{ |
conf->dhm_min_bitlen = bitlen; |
} |
#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
/* |
* Set allowed/preferred hashes for handshake signatures |
*/ |
void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, |
const int *hashes ) |
{ |
conf->sig_hashes = hashes; |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
#if defined(MBEDTLS_ECP_C) |
/* |
* Set the allowed elliptic curves |
*/ |
void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, |
const mbedtls_ecp_group_id *curve_list ) |
{ |
conf->curve_list = curve_list; |
} |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) |
{ |
/* Initialize to suppress unnecessary compiler warning */ |
size_t hostname_len = 0; |
/* Check if new hostname is valid before |
* making any change to current one */ |
if( hostname != NULL ) |
{ |
hostname_len = strlen( hostname ); |
if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
/* Now it's clear that we will overwrite the old hostname, |
* so we can free it safely */ |
if( ssl->hostname != NULL ) |
{ |
mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); |
mbedtls_free( ssl->hostname ); |
} |
/* Passing NULL as hostname shall clear the old one */ |
if( hostname == NULL ) |
{ |
ssl->hostname = NULL; |
} |
else |
{ |
ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); |
if( ssl->hostname == NULL ) |
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); |
memcpy( ssl->hostname, hostname, hostname_len ); |
ssl->hostname[hostname_len] = '\0'; |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, |
int (*f_sni)(void *, mbedtls_ssl_context *, |
const unsigned char *, size_t), |
void *p_sni ) |
{ |
conf->f_sni = f_sni; |
conf->p_sni = p_sni; |
} |
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ |
#if defined(MBEDTLS_SSL_ALPN) |
int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) |
{ |
size_t cur_len, tot_len; |
const char **p; |
/* |
* RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings |
* MUST NOT be truncated." |
* We check lengths now rather than later. |
*/ |
tot_len = 0; |
for( p = protos; *p != NULL; p++ ) |
{ |
cur_len = strlen( *p ); |
tot_len += cur_len; |
if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
conf->alpn_list = protos; |
return( 0 ); |
} |
const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) |
{ |
return( ssl->alpn_chosen ); |
} |
#endif /* MBEDTLS_SSL_ALPN */ |
void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) |
{ |
conf->max_major_ver = major; |
conf->max_minor_ver = minor; |
} |
void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) |
{ |
conf->min_major_ver = major; |
conf->min_minor_ver = minor; |
} |
#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) |
void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) |
{ |
conf->fallback = fallback; |
} |
#endif |
#if defined(MBEDTLS_SSL_SRV_C) |
void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, |
char cert_req_ca_list ) |
{ |
conf->cert_req_ca_list = cert_req_ca_list; |
} |
#endif |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) |
{ |
conf->encrypt_then_mac = etm; |
} |
#endif |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) |
{ |
conf->extended_ms = ems; |
} |
#endif |
#if defined(MBEDTLS_ARC4_C) |
void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) |
{ |
conf->arc4_disabled = arc4; |
} |
#endif |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) |
{ |
if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || |
ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) |
{ |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
conf->mfl_code = mfl_code; |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) |
{ |
conf->trunc_hmac = truncate; |
} |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) |
void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) |
{ |
conf->cbc_record_splitting = split; |
} |
#endif |
void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) |
{ |
conf->allow_legacy_renegotiation = allow_legacy; |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) |
{ |
conf->disable_renegotiation = renegotiation; |
} |
void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) |
{ |
conf->renego_max_records = max_records; |
} |
void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, |
const unsigned char period[8] ) |
{ |
memcpy( conf->renego_period, period, 8 ); |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
#if defined(MBEDTLS_SSL_CLI_C) |
void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) |
{ |
conf->session_tickets = use_tickets; |
} |
#endif |
#if defined(MBEDTLS_SSL_SRV_C) |
void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, |
mbedtls_ssl_ticket_write_t *f_ticket_write, |
mbedtls_ssl_ticket_parse_t *f_ticket_parse, |
void *p_ticket ) |
{ |
conf->f_ticket_write = f_ticket_write; |
conf->f_ticket_parse = f_ticket_parse; |
conf->p_ticket = p_ticket; |
} |
#endif |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
#if defined(MBEDTLS_SSL_EXPORT_KEYS) |
void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, |
mbedtls_ssl_export_keys_t *f_export_keys, |
void *p_export_keys ) |
{ |
conf->f_export_keys = f_export_keys; |
conf->p_export_keys = p_export_keys; |
} |
#endif |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
void mbedtls_ssl_conf_async_private_cb( |
mbedtls_ssl_config *conf, |
mbedtls_ssl_async_sign_t *f_async_sign, |
mbedtls_ssl_async_decrypt_t *f_async_decrypt, |
mbedtls_ssl_async_resume_t *f_async_resume, |
mbedtls_ssl_async_cancel_t *f_async_cancel, |
void *async_config_data ) |
{ |
conf->f_async_sign_start = f_async_sign; |
conf->f_async_decrypt_start = f_async_decrypt; |
conf->f_async_resume = f_async_resume; |
conf->f_async_cancel = f_async_cancel; |
conf->p_async_config_data = async_config_data; |
} |
void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) |
{ |
return( conf->p_async_config_data ); |
} |
void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) |
{ |
if( ssl->handshake == NULL ) |
return( NULL ); |
else |
return( ssl->handshake->user_async_ctx ); |
} |
void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, |
void *ctx ) |
{ |
if( ssl->handshake != NULL ) |
ssl->handshake->user_async_ctx = ctx; |
} |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
/* |
* SSL get accessors |
*/ |
size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) |
{ |
return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); |
} |
int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) |
{ |
/* |
* Case A: We're currently holding back |
* a message for further processing. |
*/ |
if( ssl->keep_current_message == 1 ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); |
return( 1 ); |
} |
/* |
* Case B: Further records are pending in the current datagram. |
*/ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->in_left > ssl->next_record_offset ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); |
return( 1 ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
/* |
* Case C: A handshake message is being processed. |
*/ |
if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); |
return( 1 ); |
} |
/* |
* Case D: An application data message is being processed |
*/ |
if( ssl->in_offt != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); |
return( 1 ); |
} |
/* |
* In all other cases, the rest of the message can be dropped. |
* As in ssl_get_next_record, this needs to be adapted if |
* we implement support for multiple alerts in single records. |
*/ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); |
return( 0 ); |
} |
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) |
{ |
if( ssl->session != NULL ) |
return( ssl->session->verify_result ); |
if( ssl->session_negotiate != NULL ) |
return( ssl->session_negotiate->verify_result ); |
return( 0xFFFFFFFF ); |
} |
const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) |
{ |
if( ssl == NULL || ssl->session == NULL ) |
return( NULL ); |
return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); |
} |
const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
switch( ssl->minor_ver ) |
{ |
case MBEDTLS_SSL_MINOR_VERSION_2: |
return( "DTLSv1.0" ); |
case MBEDTLS_SSL_MINOR_VERSION_3: |
return( "DTLSv1.2" ); |
default: |
return( "unknown (DTLS)" ); |
} |
} |
#endif |
switch( ssl->minor_ver ) |
{ |
case MBEDTLS_SSL_MINOR_VERSION_0: |
return( "SSLv3.0" ); |
case MBEDTLS_SSL_MINOR_VERSION_1: |
return( "TLSv1.0" ); |
case MBEDTLS_SSL_MINOR_VERSION_2: |
return( "TLSv1.1" ); |
case MBEDTLS_SSL_MINOR_VERSION_3: |
return( "TLSv1.2" ); |
default: |
return( "unknown" ); |
} |
} |
int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) |
{ |
size_t transform_expansion = 0; |
const mbedtls_ssl_transform *transform = ssl->transform_out; |
unsigned block_size; |
if( transform == NULL ) |
return( (int) mbedtls_ssl_hdr_len( ssl ) ); |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) |
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); |
#endif |
switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) |
{ |
case MBEDTLS_MODE_GCM: |
case MBEDTLS_MODE_CCM: |
case MBEDTLS_MODE_CHACHAPOLY: |
case MBEDTLS_MODE_STREAM: |
transform_expansion = transform->minlen; |
break; |
case MBEDTLS_MODE_CBC: |
block_size = mbedtls_cipher_get_block_size( |
&transform->cipher_ctx_enc ); |
/* Expansion due to the addition of the MAC. */ |
transform_expansion += transform->maclen; |
/* Expansion due to the addition of CBC padding; |
* Theoretically up to 256 bytes, but we never use |
* more than the block size of the underlying cipher. */ |
transform_expansion += block_size; |
/* For TLS 1.1 or higher, an explicit IV is added |
* after the record header. */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) |
transform_expansion += block_size; |
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ |
break; |
default: |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); |
} |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) |
{ |
size_t max_len; |
/* |
* Assume mfl_code is correct since it was checked when set |
*/ |
max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); |
/* Check if a smaller max length was negotiated */ |
if( ssl->session_out != NULL && |
ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) |
{ |
max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); |
} |
/* During a handshake, use the value being negotiated */ |
if( ssl->session_negotiate != NULL && |
ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len ) |
{ |
max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); |
} |
return( max_len ); |
} |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) |
{ |
/* Return unlimited mtu for client hello messages to avoid fragmentation. */ |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && |
( ssl->state == MBEDTLS_SSL_CLIENT_HELLO || |
ssl->state == MBEDTLS_SSL_SERVER_HELLO ) ) |
return ( 0 ); |
if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) |
return( ssl->mtu ); |
if( ssl->mtu == 0 ) |
return( ssl->handshake->mtu ); |
return( ssl->mtu < ssl->handshake->mtu ? |
ssl->mtu : ssl->handshake->mtu ); |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) |
{ |
size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; |
#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ |
!defined(MBEDTLS_SSL_PROTO_DTLS) |
(void) ssl; |
#endif |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); |
if( max_len > mfl ) |
max_len = mfl; |
#endif |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl_get_current_mtu( ssl ) != 0 ) |
{ |
const size_t mtu = ssl_get_current_mtu( ssl ); |
const int ret = mbedtls_ssl_get_record_expansion( ssl ); |
const size_t overhead = (size_t) ret; |
if( ret < 0 ) |
return( ret ); |
if( mtu <= overhead ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) ); |
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); |
} |
if( max_len > mtu - overhead ) |
max_len = mtu - overhead; |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ |
!defined(MBEDTLS_SSL_PROTO_DTLS) |
((void) ssl); |
#endif |
return( (int) max_len ); |
} |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) |
{ |
if( ssl == NULL || ssl->session == NULL ) |
return( NULL ); |
return( ssl->session->peer_cert ); |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
#if defined(MBEDTLS_SSL_CLI_C) |
int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst ) |
{ |
if( ssl == NULL || |
dst == NULL || |
ssl->session == NULL || |
ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) |
{ |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
return( ssl_session_copy( dst, ssl->session ) ); |
} |
#endif /* MBEDTLS_SSL_CLI_C */ |
/* |
* Perform a single step of the SSL handshake |
*/ |
int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
if( ssl == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_SSL_CLI_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) |
ret = mbedtls_ssl_handshake_client_step( ssl ); |
#endif |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
ret = mbedtls_ssl_handshake_server_step( ssl ); |
#endif |
return( ret ); |
} |
/* |
* Perform the SSL handshake |
*/ |
int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) |
{ |
int ret = 0; |
if( ssl == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); |
while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) |
{ |
ret = mbedtls_ssl_handshake_step( ssl ); |
if( ret != 0 ) |
break; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); |
return( ret ); |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
#if defined(MBEDTLS_SSL_SRV_C) |
/* |
* Write HelloRequest to request renegotiation on server |
*/ |
static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); |
ssl->out_msglen = 4; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; |
ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; |
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SSL_SRV_C */ |
/* |
* Actually renegotiate current connection, triggered by either: |
* - any side: calling mbedtls_ssl_renegotiate(), |
* - client: receiving a HelloRequest during mbedtls_ssl_read(), |
* - server: receiving any handshake message on server during mbedtls_ssl_read() after |
* the initial handshake is completed. |
* If the handshake doesn't complete due to waiting for I/O, it will continue |
* during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. |
*/ |
static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); |
if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) |
return( ret ); |
/* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and |
* the ServerHello will have message_seq = 1" */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) |
{ |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
ssl->handshake->out_msg_seq = 1; |
else |
ssl->handshake->in_msg_seq = 1; |
} |
#endif |
ssl->state = MBEDTLS_SSL_HELLO_REQUEST; |
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; |
if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); |
return( ret ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); |
return( 0 ); |
} |
/* |
* Renegotiate current connection on client, |
* or request renegotiation on server |
*/ |
int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) |
{ |
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; |
if( ssl == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_SSL_SRV_C) |
/* On server, just send the request */ |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) |
{ |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; |
/* Did we already try/start sending HelloRequest? */ |
if( ssl->out_left != 0 ) |
return( mbedtls_ssl_flush_output( ssl ) ); |
return( ssl_write_hello_request( ssl ) ); |
} |
#endif /* MBEDTLS_SSL_SRV_C */ |
#if defined(MBEDTLS_SSL_CLI_C) |
/* |
* On client, either start the renegotiation process or, |
* if already in progress, continue the handshake |
*/ |
if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) |
{ |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); |
return( ret ); |
} |
} |
else |
{ |
if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); |
return( ret ); |
} |
} |
#endif /* MBEDTLS_SSL_CLI_C */ |
return( ret ); |
} |
/* |
* Check record counters and renegotiate if they're above the limit. |
*/ |
static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) |
{ |
size_t ep_len = ssl_ep_len( ssl ); |
int in_ctr_cmp; |
int out_ctr_cmp; |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || |
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || |
ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) |
{ |
return( 0 ); |
} |
in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, |
ssl->conf->renego_period + ep_len, 8 - ep_len ); |
out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, |
ssl->conf->renego_period + ep_len, 8 - ep_len ); |
if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) |
{ |
return( 0 ); |
} |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); |
return( mbedtls_ssl_renegotiate( ssl ) ); |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
/* |
* Receive application data decrypted from the SSL layer |
*/ |
int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) |
{ |
int ret; |
size_t n; |
if( ssl == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
return( ret ); |
if( ssl->handshake != NULL && |
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) |
{ |
if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) |
return( ret ); |
} |
} |
#endif |
/* |
* Check if renegotiation is necessary and/or handshake is |
* in process. If yes, perform/continue, and fall through |
* if an unexpected packet is received while the client |
* is waiting for the ServerHello. |
* |
* (There is no equivalent to the last condition on |
* the server-side as it is not treated as within |
* a handshake while waiting for the ClientHello |
* after a renegotiation request.) |
*/ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
ret = ssl_check_ctr_renegotiate( ssl ); |
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && |
ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); |
return( ret ); |
} |
#endif |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) |
{ |
ret = mbedtls_ssl_handshake( ssl ); |
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && |
ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); |
return( ret ); |
} |
} |
/* Loop as long as no application data record is available */ |
while( ssl->in_offt == NULL ) |
{ |
/* Start timer if not already running */ |
if( ssl->f_get_timer != NULL && |
ssl->f_get_timer( ssl->p_timer ) == -1 ) |
{ |
ssl_set_timer( ssl, ssl->conf->read_timeout ); |
} |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) |
return( 0 ); |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
if( ssl->in_msglen == 0 && |
ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) |
{ |
/* |
* OpenSSL sends empty messages to randomize the IV |
*/ |
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) |
return( 0 ); |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); |
return( ret ); |
} |
} |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); |
/* |
* - For client-side, expect SERVER_HELLO_REQUEST. |
* - For server-side, expect CLIENT_HELLO. |
* - Fail (TLS) or silently drop record (DTLS) in other cases. |
*/ |
#if defined(MBEDTLS_SSL_CLI_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && |
( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || |
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); |
/* With DTLS, drop the packet (probably from last handshake) */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
continue; |
} |
#endif |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
#endif /* MBEDTLS_SSL_CLI_C */ |
#if defined(MBEDTLS_SSL_SRV_C) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); |
/* With DTLS, drop the packet (probably from last handshake) */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
continue; |
} |
#endif |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
#endif /* MBEDTLS_SSL_SRV_C */ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
/* Determine whether renegotiation attempt should be accepted */ |
if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || |
( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && |
ssl->conf->allow_legacy_renegotiation == |
MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) |
{ |
/* |
* Accept renegotiation request |
*/ |
/* DTLS clients need to know renego is server-initiated */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && |
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) |
{ |
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; |
} |
#endif |
ret = ssl_start_renegotiation( ssl ); |
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && |
ret != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
{ |
/* |
* Refuse renegotiation |
*/ |
MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) |
{ |
/* SSLv3 does not have a "no_renegotiation" warning, so |
we send a fatal alert and abort the connection. */ |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) |
{ |
if( ( ret = mbedtls_ssl_send_alert_message( ssl, |
MBEDTLS_SSL_ALERT_LEVEL_WARNING, |
MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) |
{ |
return( ret ); |
} |
} |
else |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); |
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); |
} |
} |
/* At this point, we don't know whether the renegotiation has been |
* completed or not. The cases to consider are the following: |
* 1) The renegotiation is complete. In this case, no new record |
* has been read yet. |
* 2) The renegotiation is incomplete because the client received |
* an application data record while awaiting the ServerHello. |
* 3) The renegotiation is incomplete because the client received |
* a non-handshake, non-application data message while awaiting |
* the ServerHello. |
* In each of these case, looping will be the proper action: |
* - For 1), the next iteration will read a new record and check |
* if it's application data. |
* - For 2), the loop condition isn't satisfied as application data |
* is present, hence continue is the same as break |
* - For 3), the loop condition is satisfied and read_record |
* will re-deliver the message that was held back by the client |
* when expecting the ServerHello. |
*/ |
continue; |
} |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) |
{ |
if( ssl->conf->renego_max_records >= 0 ) |
{ |
if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " |
"but not honored by client" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
} |
} |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
/* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ |
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); |
return( MBEDTLS_ERR_SSL_WANT_READ ); |
} |
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); |
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); |
} |
ssl->in_offt = ssl->in_msg; |
/* We're going to return something now, cancel timer, |
* except if handshake (renegotiation) is in progress */ |
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) |
ssl_set_timer( ssl, 0 ); |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
/* If we requested renego but received AppData, resend HelloRequest. |
* Do it now, after setting in_offt, to avoid taking this branch |
* again if ssl_write_hello_request() returns WANT_WRITE */ |
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && |
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) |
{ |
if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); |
return( ret ); |
} |
} |
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
} |
n = ( len < ssl->in_msglen ) |
? len : ssl->in_msglen; |
memcpy( buf, ssl->in_offt, n ); |
ssl->in_msglen -= n; |
if( ssl->in_msglen == 0 ) |
{ |
/* all bytes consumed */ |
ssl->in_offt = NULL; |
ssl->keep_current_message = 0; |
} |
else |
{ |
/* more data available */ |
ssl->in_offt += n; |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); |
return( (int) n ); |
} |
/* |
* Send application data to be encrypted by the SSL layer, taking care of max |
* fragment length and buffer size. |
* |
* According to RFC 5246 Section 6.2.1: |
* |
* Zero-length fragments of Application data MAY be sent as they are |
* potentially useful as a traffic analysis countermeasure. |
* |
* Therefore, it is possible that the input message length is 0 and the |
* corresponding return code is 0 on success. |
*/ |
static int ssl_write_real( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); |
const size_t max_len = (size_t) ret; |
if( ret < 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); |
return( ret ); |
} |
if( len > max_len ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " |
"maximum fragment length: %d > %d", |
len, max_len ) ); |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
} |
else |
#endif |
len = max_len; |
} |
if( ssl->out_left != 0 ) |
{ |
/* |
* The user has previously tried to send the data and |
* MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially |
* written. In this case, we expect the high-level write function |
* (e.g. mbedtls_ssl_write()) to be called with the same parameters |
*/ |
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); |
return( ret ); |
} |
} |
else |
{ |
/* |
* The user is trying to send a message the first time, so we need to |
* copy the data into the internal buffers and setup the data structure |
* to keep track of partial writes |
*/ |
ssl->out_msglen = len; |
ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; |
memcpy( ssl->out_msg, buf, len ); |
if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); |
return( ret ); |
} |
} |
return( (int) len ); |
} |
/* |
* Write application data, doing 1/n-1 splitting if necessary. |
* |
* With non-blocking I/O, ssl_write_real() may return WANT_WRITE, |
* then the caller will call us again with the same arguments, so |
* remember whether we already did the split or not. |
*/ |
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) |
static int ssl_write_split( mbedtls_ssl_context *ssl, |
const unsigned char *buf, size_t len ) |
{ |
int ret; |
if( ssl->conf->cbc_record_splitting == |
MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || |
len <= 1 || |
ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || |
mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) |
!= MBEDTLS_MODE_CBC ) |
{ |
return( ssl_write_real( ssl, buf, len ) ); |
} |
if( ssl->split_done == 0 ) |
{ |
if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) |
return( ret ); |
ssl->split_done = 1; |
} |
if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) |
return( ret ); |
ssl->split_done = 0; |
return( ret + 1 ); |
} |
#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ |
/* |
* Write application data (public-facing wrapper) |
*/ |
int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) |
{ |
int ret; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); |
if( ssl == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); |
return( ret ); |
} |
#endif |
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) |
{ |
if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); |
return( ret ); |
} |
} |
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) |
ret = ssl_write_split( ssl, buf, len ); |
#else |
ret = ssl_write_real( ssl, buf, len ); |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); |
return( ret ); |
} |
/* |
* Notify the peer that the connection is being closed |
*/ |
int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) |
{ |
int ret; |
if( ssl == NULL || ssl->conf == NULL ) |
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); |
if( ssl->out_left != 0 ) |
return( mbedtls_ssl_flush_output( ssl ) ); |
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) |
{ |
if( ( ret = mbedtls_ssl_send_alert_message( ssl, |
MBEDTLS_SSL_ALERT_LEVEL_WARNING, |
MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); |
return( ret ); |
} |
} |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); |
return( 0 ); |
} |
void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) |
{ |
if( transform == NULL ) |
return; |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
deflateEnd( &transform->ctx_deflate ); |
inflateEnd( &transform->ctx_inflate ); |
#endif |
mbedtls_cipher_free( &transform->cipher_ctx_enc ); |
mbedtls_cipher_free( &transform->cipher_ctx_dec ); |
mbedtls_md_free( &transform->md_ctx_enc ); |
mbedtls_md_free( &transform->md_ctx_dec ); |
mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); |
} |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) |
{ |
mbedtls_ssl_key_cert *cur = key_cert, *next; |
while( cur != NULL ) |
{ |
next = cur->next; |
mbedtls_free( cur ); |
cur = next; |
} |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
static void ssl_buffering_free( mbedtls_ssl_context *ssl ) |
{ |
unsigned offset; |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
if( hs == NULL ) |
return; |
ssl_free_buffered_record( ssl ); |
for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) |
ssl_buffering_free_slot( ssl, offset ); |
} |
static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, |
uint8_t slot ) |
{ |
mbedtls_ssl_handshake_params * const hs = ssl->handshake; |
mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; |
if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) |
return; |
if( hs_buf->is_valid == 1 ) |
{ |
hs->buffering.total_bytes_buffered -= hs_buf->data_len; |
mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); |
mbedtls_free( hs_buf->data ); |
memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); |
} |
} |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) |
{ |
mbedtls_ssl_handshake_params *handshake = ssl->handshake; |
if( handshake == NULL ) |
return; |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) |
{ |
ssl->conf->f_async_cancel( ssl ); |
handshake->async_in_progress = 0; |
} |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
mbedtls_md5_free( &handshake->fin_md5 ); |
mbedtls_sha1_free( &handshake->fin_sha1 ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
#if defined(MBEDTLS_SHA256_C) |
mbedtls_sha256_free( &handshake->fin_sha256 ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
mbedtls_sha512_free( &handshake->fin_sha512 ); |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_DHM_C) |
mbedtls_dhm_free( &handshake->dhm_ctx ); |
#endif |
#if defined(MBEDTLS_ECDH_C) |
mbedtls_ecdh_free( &handshake->ecdh_ctx ); |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); |
#if defined(MBEDTLS_SSL_CLI_C) |
mbedtls_free( handshake->ecjpake_cache ); |
handshake->ecjpake_cache = NULL; |
handshake->ecjpake_cache_len = 0; |
#endif |
#endif |
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ |
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
/* explicit void pointer cast for buggy MS compiler */ |
mbedtls_free( (void *) handshake->curves ); |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
if( handshake->psk != NULL ) |
{ |
mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); |
mbedtls_free( handshake->psk ); |
} |
#endif |
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ |
defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
/* |
* Free only the linked list wrapper, not the keys themselves |
* since the belong to the SNI callback |
*/ |
if( handshake->sni_key_cert != NULL ) |
{ |
mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; |
while( cur != NULL ) |
{ |
next = cur->next; |
mbedtls_free( cur ); |
cur = next; |
} |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ |
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) |
mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); |
#endif |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
mbedtls_free( handshake->verify_cookie ); |
ssl_flight_free( handshake->flight ); |
ssl_buffering_free( ssl ); |
#endif |
mbedtls_platform_zeroize( handshake, |
sizeof( mbedtls_ssl_handshake_params ) ); |
} |
void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) |
{ |
if( session == NULL ) |
return; |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
if( session->peer_cert != NULL ) |
{ |
mbedtls_x509_crt_free( session->peer_cert ); |
mbedtls_free( session->peer_cert ); |
} |
#endif |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) |
mbedtls_free( session->ticket ); |
#endif |
mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); |
} |
/* |
* Free an SSL context |
*/ |
void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) |
{ |
if( ssl == NULL ) |
return; |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); |
if( ssl->out_buf != NULL ) |
{ |
mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN ); |
mbedtls_free( ssl->out_buf ); |
} |
if( ssl->in_buf != NULL ) |
{ |
mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN ); |
mbedtls_free( ssl->in_buf ); |
} |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
if( ssl->compress_buf != NULL ) |
{ |
mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); |
mbedtls_free( ssl->compress_buf ); |
} |
#endif |
if( ssl->transform ) |
{ |
mbedtls_ssl_transform_free( ssl->transform ); |
mbedtls_free( ssl->transform ); |
} |
if( ssl->handshake ) |
{ |
mbedtls_ssl_handshake_free( ssl ); |
mbedtls_ssl_transform_free( ssl->transform_negotiate ); |
mbedtls_ssl_session_free( ssl->session_negotiate ); |
mbedtls_free( ssl->handshake ); |
mbedtls_free( ssl->transform_negotiate ); |
mbedtls_free( ssl->session_negotiate ); |
} |
if( ssl->session ) |
{ |
mbedtls_ssl_session_free( ssl->session ); |
mbedtls_free( ssl->session ); |
} |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
if( ssl->hostname != NULL ) |
{ |
mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); |
mbedtls_free( ssl->hostname ); |
} |
#endif |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
if( mbedtls_ssl_hw_record_finish != NULL ) |
{ |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); |
mbedtls_ssl_hw_record_finish( ssl ); |
} |
#endif |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) |
mbedtls_free( ssl->cli_id ); |
#endif |
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); |
/* Actually clear after last debug message */ |
mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); |
} |
/* |
* Initialze mbedtls_ssl_config |
*/ |
void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) |
{ |
memset( conf, 0, sizeof( mbedtls_ssl_config ) ); |
} |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
static int ssl_preset_default_hashes[] = { |
#if defined(MBEDTLS_SHA512_C) |
MBEDTLS_MD_SHA512, |
MBEDTLS_MD_SHA384, |
#endif |
#if defined(MBEDTLS_SHA256_C) |
MBEDTLS_MD_SHA256, |
MBEDTLS_MD_SHA224, |
#endif |
#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) |
MBEDTLS_MD_SHA1, |
#endif |
MBEDTLS_MD_NONE |
}; |
#endif |
static int ssl_preset_suiteb_ciphersuites[] = { |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, |
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, |
0 |
}; |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
static int ssl_preset_suiteb_hashes[] = { |
MBEDTLS_MD_SHA256, |
MBEDTLS_MD_SHA384, |
MBEDTLS_MD_NONE |
}; |
#endif |
#if defined(MBEDTLS_ECP_C) |
static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
MBEDTLS_ECP_DP_SECP256R1, |
#endif |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
MBEDTLS_ECP_DP_SECP384R1, |
#endif |
MBEDTLS_ECP_DP_NONE |
}; |
#endif |
/* |
* Load default in mbedtls_ssl_config |
*/ |
int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, |
int endpoint, int transport, int preset ) |
{ |
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) |
int ret; |
#endif |
/* Use the functions here so that they are covered in tests, |
* but otherwise access member directly for efficiency */ |
mbedtls_ssl_conf_endpoint( conf, endpoint ); |
mbedtls_ssl_conf_transport( conf, transport ); |
/* |
* Things that are common to all presets |
*/ |
#if defined(MBEDTLS_SSL_CLI_C) |
if( endpoint == MBEDTLS_SSL_IS_CLIENT ) |
{ |
conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; |
#endif |
} |
#endif |
#if defined(MBEDTLS_ARC4_C) |
conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; |
#endif |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; |
#endif |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; |
#endif |
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) |
conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; |
#endif |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) |
conf->f_cookie_write = ssl_cookie_write_dummy; |
conf->f_cookie_check = ssl_cookie_check_dummy; |
#endif |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; |
#endif |
#if defined(MBEDTLS_SSL_SRV_C) |
conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; |
#endif |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; |
conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; |
#endif |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; |
memset( conf->renego_period, 0x00, 2 ); |
memset( conf->renego_period + 2, 0xFF, 6 ); |
#endif |
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) |
if( endpoint == MBEDTLS_SSL_IS_SERVER ) |
{ |
const unsigned char dhm_p[] = |
MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; |
const unsigned char dhm_g[] = |
MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; |
if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, |
dhm_p, sizeof( dhm_p ), |
dhm_g, sizeof( dhm_g ) ) ) != 0 ) |
{ |
return( ret ); |
} |
} |
#endif |
/* |
* Preset-specific defaults |
*/ |
switch( preset ) |
{ |
/* |
* NSA Suite B |
*/ |
case MBEDTLS_SSL_PRESET_SUITEB: |
conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; |
conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ |
conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; |
conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = |
ssl_preset_suiteb_ciphersuites; |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
conf->sig_hashes = ssl_preset_suiteb_hashes; |
#endif |
#if defined(MBEDTLS_ECP_C) |
conf->curve_list = ssl_preset_suiteb_curves; |
#endif |
break; |
/* |
* Default |
*/ |
default: |
conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION > |
MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? |
MBEDTLS_SSL_MIN_MAJOR_VERSION : |
MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; |
conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > |
MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? |
MBEDTLS_SSL_MIN_MINOR_VERSION : |
MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; |
conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; |
conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; |
#endif |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = |
conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = |
mbedtls_ssl_list_ciphersuites(); |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
conf->cert_profile = &mbedtls_x509_crt_profile_default; |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
conf->sig_hashes = ssl_preset_default_hashes; |
#endif |
#if defined(MBEDTLS_ECP_C) |
conf->curve_list = mbedtls_ecp_grp_id_list(); |
#endif |
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) |
conf->dhm_min_bitlen = 1024; |
#endif |
} |
return( 0 ); |
} |
/* |
* Free mbedtls_ssl_config |
*/ |
void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) |
{ |
#if defined(MBEDTLS_DHM_C) |
mbedtls_mpi_free( &conf->dhm_P ); |
mbedtls_mpi_free( &conf->dhm_G ); |
#endif |
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) |
if( conf->psk != NULL ) |
{ |
mbedtls_platform_zeroize( conf->psk, conf->psk_len ); |
mbedtls_free( conf->psk ); |
conf->psk = NULL; |
conf->psk_len = 0; |
} |
if( conf->psk_identity != NULL ) |
{ |
mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len ); |
mbedtls_free( conf->psk_identity ); |
conf->psk_identity = NULL; |
conf->psk_identity_len = 0; |
} |
#endif |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
ssl_key_cert_free( conf->key_cert ); |
#endif |
mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) ); |
} |
#if defined(MBEDTLS_PK_C) && \ |
( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) |
/* |
* Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX |
*/ |
unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) |
{ |
#if defined(MBEDTLS_RSA_C) |
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) |
return( MBEDTLS_SSL_SIG_RSA ); |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) |
return( MBEDTLS_SSL_SIG_ECDSA ); |
#endif |
return( MBEDTLS_SSL_SIG_ANON ); |
} |
unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) |
{ |
switch( type ) { |
case MBEDTLS_PK_RSA: |
return( MBEDTLS_SSL_SIG_RSA ); |
case MBEDTLS_PK_ECDSA: |
case MBEDTLS_PK_ECKEY: |
return( MBEDTLS_SSL_SIG_ECDSA ); |
default: |
return( MBEDTLS_SSL_SIG_ANON ); |
} |
} |
mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) |
{ |
switch( sig ) |
{ |
#if defined(MBEDTLS_RSA_C) |
case MBEDTLS_SSL_SIG_RSA: |
return( MBEDTLS_PK_RSA ); |
#endif |
#if defined(MBEDTLS_ECDSA_C) |
case MBEDTLS_SSL_SIG_ECDSA: |
return( MBEDTLS_PK_ECDSA ); |
#endif |
default: |
return( MBEDTLS_PK_NONE ); |
} |
} |
#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ |
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
/* Find an entry in a signature-hash set matching a given hash algorithm. */ |
mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, |
mbedtls_pk_type_t sig_alg ) |
{ |
switch( sig_alg ) |
{ |
case MBEDTLS_PK_RSA: |
return( set->rsa ); |
case MBEDTLS_PK_ECDSA: |
return( set->ecdsa ); |
default: |
return( MBEDTLS_MD_NONE ); |
} |
} |
/* Add a signature-hash-pair to a signature-hash set */ |
void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, |
mbedtls_pk_type_t sig_alg, |
mbedtls_md_type_t md_alg ) |
{ |
switch( sig_alg ) |
{ |
case MBEDTLS_PK_RSA: |
if( set->rsa == MBEDTLS_MD_NONE ) |
set->rsa = md_alg; |
break; |
case MBEDTLS_PK_ECDSA: |
if( set->ecdsa == MBEDTLS_MD_NONE ) |
set->ecdsa = md_alg; |
break; |
default: |
break; |
} |
} |
/* Allow exactly one hash algorithm for each signature. */ |
void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, |
mbedtls_md_type_t md_alg ) |
{ |
set->rsa = md_alg; |
set->ecdsa = md_alg; |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && |
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
/* |
* Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX |
*/ |
mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) |
{ |
switch( hash ) |
{ |
#if defined(MBEDTLS_MD5_C) |
case MBEDTLS_SSL_HASH_MD5: |
return( MBEDTLS_MD_MD5 ); |
#endif |
#if defined(MBEDTLS_SHA1_C) |
case MBEDTLS_SSL_HASH_SHA1: |
return( MBEDTLS_MD_SHA1 ); |
#endif |
#if defined(MBEDTLS_SHA256_C) |
case MBEDTLS_SSL_HASH_SHA224: |
return( MBEDTLS_MD_SHA224 ); |
case MBEDTLS_SSL_HASH_SHA256: |
return( MBEDTLS_MD_SHA256 ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
case MBEDTLS_SSL_HASH_SHA384: |
return( MBEDTLS_MD_SHA384 ); |
case MBEDTLS_SSL_HASH_SHA512: |
return( MBEDTLS_MD_SHA512 ); |
#endif |
default: |
return( MBEDTLS_MD_NONE ); |
} |
} |
/* |
* Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX |
*/ |
unsigned char mbedtls_ssl_hash_from_md_alg( int md ) |
{ |
switch( md ) |
{ |
#if defined(MBEDTLS_MD5_C) |
case MBEDTLS_MD_MD5: |
return( MBEDTLS_SSL_HASH_MD5 ); |
#endif |
#if defined(MBEDTLS_SHA1_C) |
case MBEDTLS_MD_SHA1: |
return( MBEDTLS_SSL_HASH_SHA1 ); |
#endif |
#if defined(MBEDTLS_SHA256_C) |
case MBEDTLS_MD_SHA224: |
return( MBEDTLS_SSL_HASH_SHA224 ); |
case MBEDTLS_MD_SHA256: |
return( MBEDTLS_SSL_HASH_SHA256 ); |
#endif |
#if defined(MBEDTLS_SHA512_C) |
case MBEDTLS_MD_SHA384: |
return( MBEDTLS_SSL_HASH_SHA384 ); |
case MBEDTLS_MD_SHA512: |
return( MBEDTLS_SSL_HASH_SHA512 ); |
#endif |
default: |
return( MBEDTLS_SSL_HASH_NONE ); |
} |
} |
#if defined(MBEDTLS_ECP_C) |
/* |
* Check if a curve proposed by the peer is in our list. |
* Return 0 if we're willing to use it, -1 otherwise. |
*/ |
int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) |
{ |
const mbedtls_ecp_group_id *gid; |
if( ssl->conf->curve_list == NULL ) |
return( -1 ); |
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) |
if( *gid == grp_id ) |
return( 0 ); |
return( -1 ); |
} |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) |
/* |
* Check if a hash proposed by the peer is in our list. |
* Return 0 if we're willing to use it, -1 otherwise. |
*/ |
int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, |
mbedtls_md_type_t md ) |
{ |
const int *cur; |
if( ssl->conf->sig_hashes == NULL ) |
return( -1 ); |
for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) |
if( *cur == (int) md ) |
return( 0 ); |
return( -1 ); |
} |
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, |
const mbedtls_ssl_ciphersuite_t *ciphersuite, |
int cert_endpoint, |
uint32_t *flags ) |
{ |
int ret = 0; |
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) |
int usage = 0; |
#endif |
#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) |
const char *ext_oid; |
size_t ext_len; |
#endif |
#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ |
!defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) |
((void) cert); |
((void) cert_endpoint); |
((void) flags); |
#endif |
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) |
if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) |
{ |
/* Server part of the key exchange */ |
switch( ciphersuite->key_exchange ) |
{ |
case MBEDTLS_KEY_EXCHANGE_RSA: |
case MBEDTLS_KEY_EXCHANGE_RSA_PSK: |
usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; |
break; |
case MBEDTLS_KEY_EXCHANGE_DHE_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: |
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; |
break; |
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: |
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: |
usage = MBEDTLS_X509_KU_KEY_AGREEMENT; |
break; |
/* Don't use default: we want warnings when adding new values */ |
case MBEDTLS_KEY_EXCHANGE_NONE: |
case MBEDTLS_KEY_EXCHANGE_PSK: |
case MBEDTLS_KEY_EXCHANGE_DHE_PSK: |
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: |
case MBEDTLS_KEY_EXCHANGE_ECJPAKE: |
usage = 0; |
} |
} |
else |
{ |
/* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ |
usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; |
} |
if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) |
{ |
*flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; |
ret = -1; |
} |
#else |
((void) ciphersuite); |
#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ |
#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) |
if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) |
{ |
ext_oid = MBEDTLS_OID_SERVER_AUTH; |
ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); |
} |
else |
{ |
ext_oid = MBEDTLS_OID_CLIENT_AUTH; |
ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); |
} |
if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) |
{ |
*flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; |
ret = -1; |
} |
#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ |
return( ret ); |
} |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
/* |
* Convert version numbers to/from wire format |
* and, for DTLS, to/from TLS equivalent. |
* |
* For TLS this is the identity. |
* For DTLS, use 1's complement (v -> 255 - v, and then map as follows: |
* 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) |
* 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) |
*/ |
void mbedtls_ssl_write_version( int major, int minor, int transport, |
unsigned char ver[2] ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) |
--minor; /* DTLS 1.0 stored as TLS 1.1 internally */ |
ver[0] = (unsigned char)( 255 - ( major - 2 ) ); |
ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); |
} |
else |
#else |
((void) transport); |
#endif |
{ |
ver[0] = (unsigned char) major; |
ver[1] = (unsigned char) minor; |
} |
} |
void mbedtls_ssl_read_version( int *major, int *minor, int transport, |
const unsigned char ver[2] ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) |
{ |
*major = 255 - ver[0] + 2; |
*minor = 255 - ver[1] + 1; |
if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) |
++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ |
} |
else |
#else |
((void) transport); |
#endif |
{ |
*major = ver[0]; |
*minor = ver[1]; |
} |
} |
int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) |
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; |
switch( md ) |
{ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) |
#if defined(MBEDTLS_MD5_C) |
case MBEDTLS_SSL_HASH_MD5: |
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; |
#endif |
#if defined(MBEDTLS_SHA1_C) |
case MBEDTLS_SSL_HASH_SHA1: |
ssl->handshake->calc_verify = ssl_calc_verify_tls; |
break; |
#endif |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SHA512_C) |
case MBEDTLS_SSL_HASH_SHA384: |
ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; |
break; |
#endif |
#if defined(MBEDTLS_SHA256_C) |
case MBEDTLS_SSL_HASH_SHA256: |
ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; |
break; |
#endif |
default: |
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; |
} |
return 0; |
#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ |
(void) ssl; |
(void) md; |
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
} |
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_1) |
int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, |
unsigned char *output, |
unsigned char *data, size_t data_len ) |
{ |
int ret = 0; |
mbedtls_md5_context mbedtls_md5; |
mbedtls_sha1_context mbedtls_sha1; |
mbedtls_md5_init( &mbedtls_md5 ); |
mbedtls_sha1_init( &mbedtls_sha1 ); |
/* |
* digitally-signed struct { |
* opaque md5_hash[16]; |
* opaque sha_hash[20]; |
* }; |
* |
* md5_hash |
* MD5(ClientHello.random + ServerHello.random |
* + ServerParams); |
* sha_hash |
* SHA(ClientHello.random + ServerHello.random |
* + ServerParams); |
*/ |
if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, |
ssl->handshake->randbytes, 64 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, |
ssl->handshake->randbytes, 64 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data, |
data_len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1, |
output + 16 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret ); |
goto exit; |
} |
exit: |
mbedtls_md5_free( &mbedtls_md5 ); |
mbedtls_sha1_free( &mbedtls_sha1 ); |
if( ret != 0 ) |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ |
MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ |
defined(MBEDTLS_SSL_PROTO_TLS1_2) |
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, |
unsigned char *hash, size_t *hashlen, |
unsigned char *data, size_t data_len, |
mbedtls_md_type_t md_alg ) |
{ |
int ret = 0; |
mbedtls_md_context_t ctx; |
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); |
*hashlen = mbedtls_md_get_size( md_info ); |
mbedtls_md_init( &ctx ); |
/* |
* digitally-signed struct { |
* opaque client_random[32]; |
* opaque server_random[32]; |
* ServerDHParams params; |
* }; |
*/ |
if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); |
goto exit; |
} |
if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) |
{ |
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); |
goto exit; |
} |
exit: |
mbedtls_md_free( &ctx ); |
if( ret != 0 ) |
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); |
return( ret ); |
} |
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ |
MBEDTLS_SSL_PROTO_TLS1_2 */ |
#endif /* MBEDTLS_SSL_TLS_C */ |
/programs/develop/libraries/kos_mbedtls/library/threading.c |
---|
0,0 → 1,189 |
/* |
* Threading abstraction layer |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* Ensure gmtime_r is available even with -std=c99; must be defined before |
* config.h, which pulls in glibc's features.h. Harmless on other platforms. |
*/ |
#if !defined(_POSIX_C_SOURCE) |
#define _POSIX_C_SOURCE 200112L |
#endif |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_THREADING_C) |
#include "mbedtls/threading.h" |
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) |
#if !defined(_WIN32) && (defined(unix) || \ |
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ |
defined(__MACH__))) |
#include <unistd.h> |
#endif /* !_WIN32 && (unix || __unix || __unix__ || |
* (__APPLE__ && __MACH__)) */ |
#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ |
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ |
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) |
/* |
* This is a convenience shorthand macro to avoid checking the long |
* preprocessor conditions above. Ideally, we could expose this macro in |
* platform_util.h and simply use it in platform_util.c, threading.c and |
* threading.h. However, this macro is not part of the Mbed TLS public API, so |
* we keep it private by only defining it in this file |
*/ |
#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) |
#define THREADING_USE_GMTIME |
#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ |
#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ |
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ |
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ |
#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ |
#if defined(MBEDTLS_THREADING_PTHREAD) |
static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) |
{ |
if( mutex == NULL ) |
return; |
mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; |
} |
static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) |
{ |
if( mutex == NULL || !mutex->is_valid ) |
return; |
(void) pthread_mutex_destroy( &mutex->mutex ); |
mutex->is_valid = 0; |
} |
static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) |
{ |
if( mutex == NULL || ! mutex->is_valid ) |
return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); |
if( pthread_mutex_lock( &mutex->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
return( 0 ); |
} |
static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) |
{ |
if( mutex == NULL || ! mutex->is_valid ) |
return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); |
if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) |
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); |
return( 0 ); |
} |
void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; |
void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; |
int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; |
int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; |
/* |
* With phtreads we can statically initialize mutexes |
*/ |
#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } |
#endif /* MBEDTLS_THREADING_PTHREAD */ |
#if defined(MBEDTLS_THREADING_ALT) |
static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) |
{ |
((void) mutex ); |
return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); |
} |
static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) |
{ |
((void) mutex ); |
return; |
} |
void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; |
void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; |
int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; |
int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; |
/* |
* Set functions pointers and initialize global mutexes |
*/ |
void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), |
void (*mutex_free)( mbedtls_threading_mutex_t * ), |
int (*mutex_lock)( mbedtls_threading_mutex_t * ), |
int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) |
{ |
mbedtls_mutex_init = mutex_init; |
mbedtls_mutex_free = mutex_free; |
mbedtls_mutex_lock = mutex_lock; |
mbedtls_mutex_unlock = mutex_unlock; |
#if defined(MBEDTLS_FS_IO) |
mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); |
#endif |
#if defined(THREADING_USE_GMTIME) |
mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); |
#endif |
} |
/* |
* Free global mutexes |
*/ |
void mbedtls_threading_free_alt( void ) |
{ |
#if defined(MBEDTLS_FS_IO) |
mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); |
#endif |
#if defined(THREADING_USE_GMTIME) |
mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); |
#endif |
} |
#endif /* MBEDTLS_THREADING_ALT */ |
/* |
* Define global mutexes |
*/ |
#ifndef MUTEX_INIT |
#define MUTEX_INIT |
#endif |
#if defined(MBEDTLS_FS_IO) |
mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; |
#endif |
#if defined(THREADING_USE_GMTIME) |
mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; |
#endif |
#endif /* MBEDTLS_THREADING_C */ |
/programs/develop/libraries/kos_mbedtls/library/timing.c |
---|
0,0 → 1,539 |
/* |
* Portable interface to the CPU cycle counter |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif |
#if defined(MBEDTLS_TIMING_C) |
#include "mbedtls/timing.h" |
#if !defined(MBEDTLS_TIMING_ALT) |
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ |
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ |
!defined(__HAIKU__) |
//#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" |
#endif |
#ifndef asm |
#define asm __asm |
#endif |
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) |
#include <windows.h> |
#include <process.h> |
struct _hr_time |
{ |
LARGE_INTEGER start; |
}; |
#else |
#include <unistd.h> |
#include <sys/types.h> |
#include <sys/time.h> |
#include <signal.h> |
#include <time.h> |
struct _hr_time |
{ |
struct timeval start; |
}; |
#endif /* _WIN32 && !EFIX64 && !EFI32 */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long tsc; |
__asm rdtsc |
__asm mov [tsc], eax |
return( tsc ); |
} |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ |
/* some versions of mingw-64 have 32-bit longs even on x84_64 */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
defined(__GNUC__) && ( defined(__i386__) || ( \ |
( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long lo, hi; |
asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); |
return( lo ); |
} |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
__GNUC__ && __i386__ */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long lo, hi; |
asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); |
return( lo | ( hi << 32 ) ); |
} |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
__GNUC__ && ( __amd64__ || __x86_64__ ) */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long tbl, tbu0, tbu1; |
do |
{ |
asm volatile( "mftbu %0" : "=r" (tbu0) ); |
asm volatile( "mftb %0" : "=r" (tbl ) ); |
asm volatile( "mftbu %0" : "=r" (tbu1) ); |
} |
while( tbu0 != tbu1 ); |
return( tbl ); |
} |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
__GNUC__ && ( __powerpc__ || __ppc__ ) */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
defined(__GNUC__) && defined(__sparc64__) |
#if defined(__OpenBSD__) |
#warning OpenBSD does not allow access to tick register using software version instead |
#else |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long tick; |
asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); |
return( tick ); |
} |
#endif /* __OpenBSD__ */ |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
__GNUC__ && __sparc64__ */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long tick; |
asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); |
asm volatile( "mov %%g1, %0" : "=r" (tick) ); |
return( tick ); |
} |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
__GNUC__ && __sparc__ && !__sparc64__ */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
defined(__GNUC__) && defined(__alpha__) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long cc; |
asm volatile( "rpcc %0" : "=r" (cc) ); |
return( cc & 0xFFFFFFFF ); |
} |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
__GNUC__ && __alpha__ */ |
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ |
defined(__GNUC__) && defined(__ia64__) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
unsigned long itc; |
asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); |
return( itc ); |
} |
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && |
__GNUC__ && __ia64__ */ |
#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ |
!defined(EFIX64) && !defined(EFI32) |
#define HAVE_HARDCLOCK |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
LARGE_INTEGER offset; |
QueryPerformanceCounter( &offset ); |
return( (unsigned long)( offset.QuadPart ) ); |
} |
#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ |
#if !defined(HAVE_HARDCLOCK) |
#define HAVE_HARDCLOCK |
static int hardclock_init = 0; |
static struct timeval tv_init; |
unsigned long mbedtls_timing_hardclock( void ) |
{ |
struct timeval tv_cur; |
if( hardclock_init == 0 ) |
{ |
gettimeofday( &tv_init, NULL ); |
hardclock_init = 1; |
} |
gettimeofday( &tv_cur, NULL ); |
return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 |
+ ( tv_cur.tv_usec - tv_init.tv_usec ) ); |
} |
#endif /* !HAVE_HARDCLOCK */ |
volatile int mbedtls_timing_alarmed = 0; |
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) |
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) |
{ |
struct _hr_time *t = (struct _hr_time *) val; |
if( reset ) |
{ |
QueryPerformanceCounter( &t->start ); |
return( 0 ); |
} |
else |
{ |
unsigned long delta; |
LARGE_INTEGER now, hfreq; |
QueryPerformanceCounter( &now ); |
QueryPerformanceFrequency( &hfreq ); |
delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul |
/ hfreq.QuadPart ); |
return( delta ); |
} |
} |
/* It's OK to use a global because alarm() is supposed to be global anyway */ |
static DWORD alarmMs; |
static void TimerProc( void *TimerContext ) |
{ |
(void) TimerContext; |
Sleep( alarmMs ); |
mbedtls_timing_alarmed = 1; |
/* _endthread will be called implicitly on return |
* That ensures execution of thread funcition's epilogue */ |
} |
void mbedtls_set_alarm( int seconds ) |
{ |
if( seconds == 0 ) |
{ |
/* No need to create a thread for this simple case. |
* Also, this shorcut is more reliable at least on MinGW32 */ |
mbedtls_timing_alarmed = 1; |
return; |
} |
mbedtls_timing_alarmed = 0; |
alarmMs = seconds * 1000; |
(void) _beginthread( TimerProc, 0, NULL ); |
} |
#else /* _WIN32 && !EFIX64 && !EFI32 */ |
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) |
{ |
struct _hr_time *t = (struct _hr_time *) val; |
if( reset ) |
{ |
gettimeofday( &t->start, NULL ); |
return( 0 ); |
} |
else |
{ |
unsigned long delta; |
struct timeval now; |
gettimeofday( &now, NULL ); |
delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul |
+ ( now.tv_usec - t->start.tv_usec ) / 1000; |
return( delta ); |
} |
} |
static void sighandler( int signum ) |
{ |
mbedtls_timing_alarmed = 1; |
signal( signum, sighandler ); |
} |
void mbedtls_set_alarm( int seconds ) |
{ |
mbedtls_timing_alarmed = 0; |
signal( SIGALRM, sighandler ); |
//!!!!rgimad |
//alarm( seconds ); |
if( seconds == 0 ) |
{ |
/* alarm(0) cancelled any previous pending alarm, but the |
handler won't fire, so raise the flag straight away. */ |
mbedtls_timing_alarmed = 1; |
} |
} |
#endif /* _WIN32 && !EFIX64 && !EFI32 */ |
/* |
* Set delays to watch |
*/ |
void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) |
{ |
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; |
ctx->int_ms = int_ms; |
ctx->fin_ms = fin_ms; |
if( fin_ms != 0 ) |
(void) mbedtls_timing_get_timer( &ctx->timer, 1 ); |
} |
/* |
* Get number of delays expired |
*/ |
int mbedtls_timing_get_delay( void *data ) |
{ |
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; |
unsigned long elapsed_ms; |
if( ctx->fin_ms == 0 ) |
return( -1 ); |
elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); |
if( elapsed_ms >= ctx->fin_ms ) |
return( 2 ); |
if( elapsed_ms >= ctx->int_ms ) |
return( 1 ); |
return( 0 ); |
} |
#endif /* !MBEDTLS_TIMING_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* Busy-waits for the given number of milliseconds. |
* Used for testing mbedtls_timing_hardclock. |
*/ |
static void busy_msleep( unsigned long msec ) |
{ |
struct mbedtls_timing_hr_time hires; |
unsigned long i = 0; /* for busy-waiting */ |
volatile unsigned long j; /* to prevent optimisation */ |
(void) mbedtls_timing_get_timer( &hires, 1 ); |
while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) |
i++; |
j = i; |
(void) j; |
} |
#define FAIL do \ |
{ \ |
if( verbose != 0 ) \ |
{ \ |
mbedtls_printf( "failed at line %d\n", __LINE__ ); \ |
mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ |
cycles, ratio, millisecs, secs, hardfail, \ |
(unsigned long) a, (unsigned long) b ); \ |
mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ |
mbedtls_timing_get_timer( &hires, 0 ), \ |
mbedtls_timing_get_timer( &ctx.timer, 0 ), \ |
mbedtls_timing_get_delay( &ctx ) ); \ |
} \ |
return( 1 ); \ |
} while( 0 ) |
/* |
* Checkup routine |
* |
* Warning: this is work in progress, some tests may not be reliable enough |
* yet! False positives may happen. |
*/ |
int mbedtls_timing_self_test( int verbose ) |
{ |
unsigned long cycles = 0, ratio = 0; |
unsigned long millisecs = 0, secs = 0; |
int hardfail = 0; |
struct mbedtls_timing_hr_time hires; |
uint32_t a = 0, b = 0; |
mbedtls_timing_delay_context ctx; |
if( verbose != 0 ) |
mbedtls_printf( " TIMING tests note: will take some time!\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); |
{ |
secs = 1; |
(void) mbedtls_timing_get_timer( &hires, 1 ); |
mbedtls_set_alarm( (int) secs ); |
while( !mbedtls_timing_alarmed ) |
; |
millisecs = mbedtls_timing_get_timer( &hires, 0 ); |
/* For some reason on Windows it looks like alarm has an extra delay |
* (maybe related to creating a new thread). Allow some room here. */ |
if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) |
FAIL; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); |
{ |
a = 800; |
b = 400; |
mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ |
busy_msleep( a - a / 4 ); /* T = a - a/4 */ |
if( mbedtls_timing_get_delay( &ctx ) != 0 ) |
FAIL; |
busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ |
if( mbedtls_timing_get_delay( &ctx ) != 1 ) |
FAIL; |
busy_msleep( b ); /* T = a + b + b/4 */ |
if( mbedtls_timing_get_delay( &ctx ) != 2 ) |
FAIL; |
} |
mbedtls_timing_set_delay( &ctx, 0, 0 ); |
busy_msleep( 200 ); |
if( mbedtls_timing_get_delay( &ctx ) != -1 ) |
FAIL; |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
if( verbose != 0 ) |
mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); |
/* |
* Allow one failure for possible counter wrapping. |
* On a 4Ghz 32-bit machine the cycle counter wraps about once per second; |
* since the whole test is about 10ms, it shouldn't happen twice in a row. |
*/ |
hard_test: |
if( hardfail > 1 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed (ignored)\n" ); |
goto hard_test_done; |
} |
/* Get a reference ratio cycles/ms */ |
millisecs = 1; |
cycles = mbedtls_timing_hardclock(); |
busy_msleep( millisecs ); |
cycles = mbedtls_timing_hardclock() - cycles; |
ratio = cycles / millisecs; |
/* Check that the ratio is mostly constant */ |
for( millisecs = 2; millisecs <= 4; millisecs++ ) |
{ |
cycles = mbedtls_timing_hardclock(); |
busy_msleep( millisecs ); |
cycles = mbedtls_timing_hardclock() - cycles; |
/* Allow variation up to 20% */ |
if( cycles / millisecs < ratio - ratio / 5 || |
cycles / millisecs > ratio + ratio / 5 ) |
{ |
hardfail++; |
goto hard_test; |
} |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
hard_test_done: |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
return( 0 ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_TIMING_C */ |
/programs/develop/libraries/kos_mbedtls/library/version.c |
---|
0,0 → 1,52 |
/* |
* Version information |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_VERSION_C) |
#include "mbedtls/version.h" |
#include <string.h> |
unsigned int mbedtls_version_get_number( void ) |
{ |
return( MBEDTLS_VERSION_NUMBER ); |
} |
void mbedtls_version_get_string( char *string ) |
{ |
memcpy( string, MBEDTLS_VERSION_STRING, |
sizeof( MBEDTLS_VERSION_STRING ) ); |
} |
void mbedtls_version_get_string_full( char *string ) |
{ |
memcpy( string, MBEDTLS_VERSION_STRING_FULL, |
sizeof( MBEDTLS_VERSION_STRING_FULL ) ); |
} |
#endif /* MBEDTLS_VERSION_C */ |
/programs/develop/libraries/kos_mbedtls/library/version_features.c |
---|
0,0 → 1,787 |
/* |
* Version feature information |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_VERSION_C) |
#include "mbedtls/version.h" |
#include <string.h> |
static const char *features[] = { |
#if defined(MBEDTLS_VERSION_FEATURES) |
#if defined(MBEDTLS_HAVE_ASM) |
"MBEDTLS_HAVE_ASM", |
#endif /* MBEDTLS_HAVE_ASM */ |
#if defined(MBEDTLS_NO_UDBL_DIVISION) |
"MBEDTLS_NO_UDBL_DIVISION", |
#endif /* MBEDTLS_NO_UDBL_DIVISION */ |
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) |
"MBEDTLS_NO_64BIT_MULTIPLICATION", |
#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ |
#if defined(MBEDTLS_HAVE_SSE2) |
"MBEDTLS_HAVE_SSE2", |
#endif /* MBEDTLS_HAVE_SSE2 */ |
#if defined(MBEDTLS_HAVE_TIME) |
"MBEDTLS_HAVE_TIME", |
#endif /* MBEDTLS_HAVE_TIME */ |
#if defined(MBEDTLS_HAVE_TIME_DATE) |
"MBEDTLS_HAVE_TIME_DATE", |
#endif /* MBEDTLS_HAVE_TIME_DATE */ |
#if defined(MBEDTLS_PLATFORM_MEMORY) |
"MBEDTLS_PLATFORM_MEMORY", |
#endif /* MBEDTLS_PLATFORM_MEMORY */ |
#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) |
"MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", |
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ |
#if defined(MBEDTLS_PLATFORM_EXIT_ALT) |
"MBEDTLS_PLATFORM_EXIT_ALT", |
#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ |
#if defined(MBEDTLS_PLATFORM_TIME_ALT) |
"MBEDTLS_PLATFORM_TIME_ALT", |
#endif /* MBEDTLS_PLATFORM_TIME_ALT */ |
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) |
"MBEDTLS_PLATFORM_FPRINTF_ALT", |
#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ |
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) |
"MBEDTLS_PLATFORM_PRINTF_ALT", |
#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ |
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) |
"MBEDTLS_PLATFORM_SNPRINTF_ALT", |
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ |
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) |
"MBEDTLS_PLATFORM_NV_SEED_ALT", |
#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ |
#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) |
"MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", |
#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ |
#if defined(MBEDTLS_DEPRECATED_WARNING) |
"MBEDTLS_DEPRECATED_WARNING", |
#endif /* MBEDTLS_DEPRECATED_WARNING */ |
#if defined(MBEDTLS_DEPRECATED_REMOVED) |
"MBEDTLS_DEPRECATED_REMOVED", |
#endif /* MBEDTLS_DEPRECATED_REMOVED */ |
#if defined(MBEDTLS_CHECK_PARAMS) |
"MBEDTLS_CHECK_PARAMS", |
#endif /* MBEDTLS_CHECK_PARAMS */ |
#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) |
"MBEDTLS_CHECK_PARAMS_ASSERT", |
#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ |
#if defined(MBEDTLS_TIMING_ALT) |
"MBEDTLS_TIMING_ALT", |
#endif /* MBEDTLS_TIMING_ALT */ |
#if defined(MBEDTLS_AES_ALT) |
"MBEDTLS_AES_ALT", |
#endif /* MBEDTLS_AES_ALT */ |
#if defined(MBEDTLS_ARC4_ALT) |
"MBEDTLS_ARC4_ALT", |
#endif /* MBEDTLS_ARC4_ALT */ |
#if defined(MBEDTLS_ARIA_ALT) |
"MBEDTLS_ARIA_ALT", |
#endif /* MBEDTLS_ARIA_ALT */ |
#if defined(MBEDTLS_BLOWFISH_ALT) |
"MBEDTLS_BLOWFISH_ALT", |
#endif /* MBEDTLS_BLOWFISH_ALT */ |
#if defined(MBEDTLS_CAMELLIA_ALT) |
"MBEDTLS_CAMELLIA_ALT", |
#endif /* MBEDTLS_CAMELLIA_ALT */ |
#if defined(MBEDTLS_CCM_ALT) |
"MBEDTLS_CCM_ALT", |
#endif /* MBEDTLS_CCM_ALT */ |
#if defined(MBEDTLS_CHACHA20_ALT) |
"MBEDTLS_CHACHA20_ALT", |
#endif /* MBEDTLS_CHACHA20_ALT */ |
#if defined(MBEDTLS_CHACHAPOLY_ALT) |
"MBEDTLS_CHACHAPOLY_ALT", |
#endif /* MBEDTLS_CHACHAPOLY_ALT */ |
#if defined(MBEDTLS_CMAC_ALT) |
"MBEDTLS_CMAC_ALT", |
#endif /* MBEDTLS_CMAC_ALT */ |
#if defined(MBEDTLS_DES_ALT) |
"MBEDTLS_DES_ALT", |
#endif /* MBEDTLS_DES_ALT */ |
#if defined(MBEDTLS_DHM_ALT) |
"MBEDTLS_DHM_ALT", |
#endif /* MBEDTLS_DHM_ALT */ |
#if defined(MBEDTLS_ECJPAKE_ALT) |
"MBEDTLS_ECJPAKE_ALT", |
#endif /* MBEDTLS_ECJPAKE_ALT */ |
#if defined(MBEDTLS_GCM_ALT) |
"MBEDTLS_GCM_ALT", |
#endif /* MBEDTLS_GCM_ALT */ |
#if defined(MBEDTLS_NIST_KW_ALT) |
"MBEDTLS_NIST_KW_ALT", |
#endif /* MBEDTLS_NIST_KW_ALT */ |
#if defined(MBEDTLS_MD2_ALT) |
"MBEDTLS_MD2_ALT", |
#endif /* MBEDTLS_MD2_ALT */ |
#if defined(MBEDTLS_MD4_ALT) |
"MBEDTLS_MD4_ALT", |
#endif /* MBEDTLS_MD4_ALT */ |
#if defined(MBEDTLS_MD5_ALT) |
"MBEDTLS_MD5_ALT", |
#endif /* MBEDTLS_MD5_ALT */ |
#if defined(MBEDTLS_POLY1305_ALT) |
"MBEDTLS_POLY1305_ALT", |
#endif /* MBEDTLS_POLY1305_ALT */ |
#if defined(MBEDTLS_RIPEMD160_ALT) |
"MBEDTLS_RIPEMD160_ALT", |
#endif /* MBEDTLS_RIPEMD160_ALT */ |
#if defined(MBEDTLS_RSA_ALT) |
"MBEDTLS_RSA_ALT", |
#endif /* MBEDTLS_RSA_ALT */ |
#if defined(MBEDTLS_SHA1_ALT) |
"MBEDTLS_SHA1_ALT", |
#endif /* MBEDTLS_SHA1_ALT */ |
#if defined(MBEDTLS_SHA256_ALT) |
"MBEDTLS_SHA256_ALT", |
#endif /* MBEDTLS_SHA256_ALT */ |
#if defined(MBEDTLS_SHA512_ALT) |
"MBEDTLS_SHA512_ALT", |
#endif /* MBEDTLS_SHA512_ALT */ |
#if defined(MBEDTLS_XTEA_ALT) |
"MBEDTLS_XTEA_ALT", |
#endif /* MBEDTLS_XTEA_ALT */ |
#if defined(MBEDTLS_ECP_ALT) |
"MBEDTLS_ECP_ALT", |
#endif /* MBEDTLS_ECP_ALT */ |
#if defined(MBEDTLS_MD2_PROCESS_ALT) |
"MBEDTLS_MD2_PROCESS_ALT", |
#endif /* MBEDTLS_MD2_PROCESS_ALT */ |
#if defined(MBEDTLS_MD4_PROCESS_ALT) |
"MBEDTLS_MD4_PROCESS_ALT", |
#endif /* MBEDTLS_MD4_PROCESS_ALT */ |
#if defined(MBEDTLS_MD5_PROCESS_ALT) |
"MBEDTLS_MD5_PROCESS_ALT", |
#endif /* MBEDTLS_MD5_PROCESS_ALT */ |
#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) |
"MBEDTLS_RIPEMD160_PROCESS_ALT", |
#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ |
#if defined(MBEDTLS_SHA1_PROCESS_ALT) |
"MBEDTLS_SHA1_PROCESS_ALT", |
#endif /* MBEDTLS_SHA1_PROCESS_ALT */ |
#if defined(MBEDTLS_SHA256_PROCESS_ALT) |
"MBEDTLS_SHA256_PROCESS_ALT", |
#endif /* MBEDTLS_SHA256_PROCESS_ALT */ |
#if defined(MBEDTLS_SHA512_PROCESS_ALT) |
"MBEDTLS_SHA512_PROCESS_ALT", |
#endif /* MBEDTLS_SHA512_PROCESS_ALT */ |
#if defined(MBEDTLS_DES_SETKEY_ALT) |
"MBEDTLS_DES_SETKEY_ALT", |
#endif /* MBEDTLS_DES_SETKEY_ALT */ |
#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) |
"MBEDTLS_DES_CRYPT_ECB_ALT", |
#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ |
#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) |
"MBEDTLS_DES3_CRYPT_ECB_ALT", |
#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ |
#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) |
"MBEDTLS_AES_SETKEY_ENC_ALT", |
#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ |
#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) |
"MBEDTLS_AES_SETKEY_DEC_ALT", |
#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ |
#if defined(MBEDTLS_AES_ENCRYPT_ALT) |
"MBEDTLS_AES_ENCRYPT_ALT", |
#endif /* MBEDTLS_AES_ENCRYPT_ALT */ |
#if defined(MBEDTLS_AES_DECRYPT_ALT) |
"MBEDTLS_AES_DECRYPT_ALT", |
#endif /* MBEDTLS_AES_DECRYPT_ALT */ |
#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) |
"MBEDTLS_ECDH_GEN_PUBLIC_ALT", |
#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ |
#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) |
"MBEDTLS_ECDH_COMPUTE_SHARED_ALT", |
#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ |
#if defined(MBEDTLS_ECDSA_VERIFY_ALT) |
"MBEDTLS_ECDSA_VERIFY_ALT", |
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ |
#if defined(MBEDTLS_ECDSA_SIGN_ALT) |
"MBEDTLS_ECDSA_SIGN_ALT", |
#endif /* MBEDTLS_ECDSA_SIGN_ALT */ |
#if defined(MBEDTLS_ECDSA_GENKEY_ALT) |
"MBEDTLS_ECDSA_GENKEY_ALT", |
#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ |
#if defined(MBEDTLS_ECP_INTERNAL_ALT) |
"MBEDTLS_ECP_INTERNAL_ALT", |
#endif /* MBEDTLS_ECP_INTERNAL_ALT */ |
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) |
"MBEDTLS_ECP_RANDOMIZE_JAC_ALT", |
#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ |
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) |
"MBEDTLS_ECP_ADD_MIXED_ALT", |
#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ |
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) |
"MBEDTLS_ECP_DOUBLE_JAC_ALT", |
#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ |
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) |
"MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", |
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ |
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) |
"MBEDTLS_ECP_NORMALIZE_JAC_ALT", |
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ |
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) |
"MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", |
#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ |
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) |
"MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", |
#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ |
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) |
"MBEDTLS_ECP_NORMALIZE_MXZ_ALT", |
#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ |
#if defined(MBEDTLS_TEST_NULL_ENTROPY) |
"MBEDTLS_TEST_NULL_ENTROPY", |
#endif /* MBEDTLS_TEST_NULL_ENTROPY */ |
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) |
"MBEDTLS_ENTROPY_HARDWARE_ALT", |
#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ |
#if defined(MBEDTLS_AES_ROM_TABLES) |
"MBEDTLS_AES_ROM_TABLES", |
#endif /* MBEDTLS_AES_ROM_TABLES */ |
#if defined(MBEDTLS_AES_FEWER_TABLES) |
"MBEDTLS_AES_FEWER_TABLES", |
#endif /* MBEDTLS_AES_FEWER_TABLES */ |
#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) |
"MBEDTLS_CAMELLIA_SMALL_MEMORY", |
#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
"MBEDTLS_CIPHER_MODE_CBC", |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#if defined(MBEDTLS_CIPHER_MODE_CFB) |
"MBEDTLS_CIPHER_MODE_CFB", |
#endif /* MBEDTLS_CIPHER_MODE_CFB */ |
#if defined(MBEDTLS_CIPHER_MODE_CTR) |
"MBEDTLS_CIPHER_MODE_CTR", |
#endif /* MBEDTLS_CIPHER_MODE_CTR */ |
#if defined(MBEDTLS_CIPHER_MODE_OFB) |
"MBEDTLS_CIPHER_MODE_OFB", |
#endif /* MBEDTLS_CIPHER_MODE_OFB */ |
#if defined(MBEDTLS_CIPHER_MODE_XTS) |
"MBEDTLS_CIPHER_MODE_XTS", |
#endif /* MBEDTLS_CIPHER_MODE_XTS */ |
#if defined(MBEDTLS_CIPHER_NULL_CIPHER) |
"MBEDTLS_CIPHER_NULL_CIPHER", |
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ |
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) |
"MBEDTLS_CIPHER_PADDING_PKCS7", |
#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ |
#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) |
"MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", |
#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ |
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) |
"MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", |
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ |
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) |
"MBEDTLS_CIPHER_PADDING_ZEROS", |
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ |
#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) |
"MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", |
#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ |
#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) |
"MBEDTLS_ENABLE_WEAK_CIPHERSUITES", |
#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ |
#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) |
"MBEDTLS_REMOVE_ARC4_CIPHERSUITES", |
#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ |
#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) |
"MBEDTLS_REMOVE_3DES_CIPHERSUITES", |
#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ |
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) |
"MBEDTLS_ECP_DP_SECP192R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) |
"MBEDTLS_ECP_DP_SECP224R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) |
"MBEDTLS_ECP_DP_SECP256R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) |
"MBEDTLS_ECP_DP_SECP384R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) |
"MBEDTLS_ECP_DP_SECP521R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) |
"MBEDTLS_ECP_DP_SECP192K1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) |
"MBEDTLS_ECP_DP_SECP224K1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) |
"MBEDTLS_ECP_DP_SECP256K1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) |
"MBEDTLS_ECP_DP_BP256R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) |
"MBEDTLS_ECP_DP_BP384R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) |
"MBEDTLS_ECP_DP_BP512R1_ENABLED", |
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) |
"MBEDTLS_ECP_DP_CURVE25519_ENABLED", |
#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ |
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) |
"MBEDTLS_ECP_DP_CURVE448_ENABLED", |
#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ |
#if defined(MBEDTLS_ECP_NIST_OPTIM) |
"MBEDTLS_ECP_NIST_OPTIM", |
#endif /* MBEDTLS_ECP_NIST_OPTIM */ |
#if defined(MBEDTLS_ECP_RESTARTABLE) |
"MBEDTLS_ECP_RESTARTABLE", |
#endif /* MBEDTLS_ECP_RESTARTABLE */ |
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) |
"MBEDTLS_ECDSA_DETERMINISTIC", |
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ |
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ |
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) |
"MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", |
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ |
#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) |
"MBEDTLS_PK_PARSE_EC_EXTENDED", |
#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ |
#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) |
"MBEDTLS_ERROR_STRERROR_DUMMY", |
#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ |
#if defined(MBEDTLS_GENPRIME) |
"MBEDTLS_GENPRIME", |
#endif /* MBEDTLS_GENPRIME */ |
#if defined(MBEDTLS_FS_IO) |
"MBEDTLS_FS_IO", |
#endif /* MBEDTLS_FS_IO */ |
#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) |
"MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", |
#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ |
#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) |
"MBEDTLS_NO_PLATFORM_ENTROPY", |
#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ |
#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) |
"MBEDTLS_ENTROPY_FORCE_SHA256", |
#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ |
#if defined(MBEDTLS_ENTROPY_NV_SEED) |
"MBEDTLS_ENTROPY_NV_SEED", |
#endif /* MBEDTLS_ENTROPY_NV_SEED */ |
#if defined(MBEDTLS_MEMORY_DEBUG) |
"MBEDTLS_MEMORY_DEBUG", |
#endif /* MBEDTLS_MEMORY_DEBUG */ |
#if defined(MBEDTLS_MEMORY_BACKTRACE) |
"MBEDTLS_MEMORY_BACKTRACE", |
#endif /* MBEDTLS_MEMORY_BACKTRACE */ |
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) |
"MBEDTLS_PK_RSA_ALT_SUPPORT", |
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ |
#if defined(MBEDTLS_PKCS1_V15) |
"MBEDTLS_PKCS1_V15", |
#endif /* MBEDTLS_PKCS1_V15 */ |
#if defined(MBEDTLS_PKCS1_V21) |
"MBEDTLS_PKCS1_V21", |
#endif /* MBEDTLS_PKCS1_V21 */ |
#if defined(MBEDTLS_RSA_NO_CRT) |
"MBEDTLS_RSA_NO_CRT", |
#endif /* MBEDTLS_RSA_NO_CRT */ |
#if defined(MBEDTLS_SELF_TEST) |
"MBEDTLS_SELF_TEST", |
#endif /* MBEDTLS_SELF_TEST */ |
#if defined(MBEDTLS_SHA256_SMALLER) |
"MBEDTLS_SHA256_SMALLER", |
#endif /* MBEDTLS_SHA256_SMALLER */ |
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) |
"MBEDTLS_SSL_ALL_ALERT_MESSAGES", |
#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ |
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) |
"MBEDTLS_SSL_ASYNC_PRIVATE", |
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ |
#if defined(MBEDTLS_SSL_DEBUG_ALL) |
"MBEDTLS_SSL_DEBUG_ALL", |
#endif /* MBEDTLS_SSL_DEBUG_ALL */ |
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) |
"MBEDTLS_SSL_ENCRYPT_THEN_MAC", |
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ |
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) |
"MBEDTLS_SSL_EXTENDED_MASTER_SECRET", |
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ |
#if defined(MBEDTLS_SSL_FALLBACK_SCSV) |
"MBEDTLS_SSL_FALLBACK_SCSV", |
#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ |
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) |
"MBEDTLS_SSL_HW_RECORD_ACCEL", |
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ |
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) |
"MBEDTLS_SSL_CBC_RECORD_SPLITTING", |
#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ |
#if defined(MBEDTLS_SSL_RENEGOTIATION) |
"MBEDTLS_SSL_RENEGOTIATION", |
#endif /* MBEDTLS_SSL_RENEGOTIATION */ |
#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) |
"MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", |
#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ |
#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) |
"MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", |
#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ |
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) |
"MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", |
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ |
#if defined(MBEDTLS_SSL_PROTO_SSL3) |
"MBEDTLS_SSL_PROTO_SSL3", |
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1) |
"MBEDTLS_SSL_PROTO_TLS1", |
#endif /* MBEDTLS_SSL_PROTO_TLS1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) |
"MBEDTLS_SSL_PROTO_TLS1_1", |
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ |
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) |
"MBEDTLS_SSL_PROTO_TLS1_2", |
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ |
#if defined(MBEDTLS_SSL_PROTO_DTLS) |
"MBEDTLS_SSL_PROTO_DTLS", |
#endif /* MBEDTLS_SSL_PROTO_DTLS */ |
#if defined(MBEDTLS_SSL_ALPN) |
"MBEDTLS_SSL_ALPN", |
#endif /* MBEDTLS_SSL_ALPN */ |
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) |
"MBEDTLS_SSL_DTLS_ANTI_REPLAY", |
#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ |
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) |
"MBEDTLS_SSL_DTLS_HELLO_VERIFY", |
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ |
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) |
"MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", |
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ |
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) |
"MBEDTLS_SSL_DTLS_BADMAC_LIMIT", |
#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ |
#if defined(MBEDTLS_SSL_SESSION_TICKETS) |
"MBEDTLS_SSL_SESSION_TICKETS", |
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ |
#if defined(MBEDTLS_SSL_EXPORT_KEYS) |
"MBEDTLS_SSL_EXPORT_KEYS", |
#endif /* MBEDTLS_SSL_EXPORT_KEYS */ |
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) |
"MBEDTLS_SSL_SERVER_NAME_INDICATION", |
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) |
"MBEDTLS_SSL_TRUNCATED_HMAC", |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ |
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) |
"MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", |
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ |
#if defined(MBEDTLS_THREADING_ALT) |
"MBEDTLS_THREADING_ALT", |
#endif /* MBEDTLS_THREADING_ALT */ |
#if defined(MBEDTLS_THREADING_PTHREAD) |
"MBEDTLS_THREADING_PTHREAD", |
#endif /* MBEDTLS_THREADING_PTHREAD */ |
#if defined(MBEDTLS_VERSION_FEATURES) |
"MBEDTLS_VERSION_FEATURES", |
#endif /* MBEDTLS_VERSION_FEATURES */ |
#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) |
"MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", |
#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ |
#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) |
"MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", |
#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ |
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) |
"MBEDTLS_X509_CHECK_KEY_USAGE", |
#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ |
#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) |
"MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", |
#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ |
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
"MBEDTLS_X509_RSASSA_PSS_SUPPORT", |
#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ |
#if defined(MBEDTLS_ZLIB_SUPPORT) |
"MBEDTLS_ZLIB_SUPPORT", |
#endif /* MBEDTLS_ZLIB_SUPPORT */ |
#if defined(MBEDTLS_AESNI_C) |
"MBEDTLS_AESNI_C", |
#endif /* MBEDTLS_AESNI_C */ |
#if defined(MBEDTLS_AES_C) |
"MBEDTLS_AES_C", |
#endif /* MBEDTLS_AES_C */ |
#if defined(MBEDTLS_ARC4_C) |
"MBEDTLS_ARC4_C", |
#endif /* MBEDTLS_ARC4_C */ |
#if defined(MBEDTLS_ASN1_PARSE_C) |
"MBEDTLS_ASN1_PARSE_C", |
#endif /* MBEDTLS_ASN1_PARSE_C */ |
#if defined(MBEDTLS_ASN1_WRITE_C) |
"MBEDTLS_ASN1_WRITE_C", |
#endif /* MBEDTLS_ASN1_WRITE_C */ |
#if defined(MBEDTLS_BASE64_C) |
"MBEDTLS_BASE64_C", |
#endif /* MBEDTLS_BASE64_C */ |
#if defined(MBEDTLS_BIGNUM_C) |
"MBEDTLS_BIGNUM_C", |
#endif /* MBEDTLS_BIGNUM_C */ |
#if defined(MBEDTLS_BLOWFISH_C) |
"MBEDTLS_BLOWFISH_C", |
#endif /* MBEDTLS_BLOWFISH_C */ |
#if defined(MBEDTLS_CAMELLIA_C) |
"MBEDTLS_CAMELLIA_C", |
#endif /* MBEDTLS_CAMELLIA_C */ |
#if defined(MBEDTLS_ARIA_C) |
"MBEDTLS_ARIA_C", |
#endif /* MBEDTLS_ARIA_C */ |
#if defined(MBEDTLS_CCM_C) |
"MBEDTLS_CCM_C", |
#endif /* MBEDTLS_CCM_C */ |
#if defined(MBEDTLS_CERTS_C) |
"MBEDTLS_CERTS_C", |
#endif /* MBEDTLS_CERTS_C */ |
#if defined(MBEDTLS_CHACHA20_C) |
"MBEDTLS_CHACHA20_C", |
#endif /* MBEDTLS_CHACHA20_C */ |
#if defined(MBEDTLS_CHACHAPOLY_C) |
"MBEDTLS_CHACHAPOLY_C", |
#endif /* MBEDTLS_CHACHAPOLY_C */ |
#if defined(MBEDTLS_CIPHER_C) |
"MBEDTLS_CIPHER_C", |
#endif /* MBEDTLS_CIPHER_C */ |
#if defined(MBEDTLS_CMAC_C) |
"MBEDTLS_CMAC_C", |
#endif /* MBEDTLS_CMAC_C */ |
#if defined(MBEDTLS_CTR_DRBG_C) |
"MBEDTLS_CTR_DRBG_C", |
#endif /* MBEDTLS_CTR_DRBG_C */ |
#if defined(MBEDTLS_DEBUG_C) |
"MBEDTLS_DEBUG_C", |
#endif /* MBEDTLS_DEBUG_C */ |
#if defined(MBEDTLS_DES_C) |
"MBEDTLS_DES_C", |
#endif /* MBEDTLS_DES_C */ |
#if defined(MBEDTLS_DHM_C) |
"MBEDTLS_DHM_C", |
#endif /* MBEDTLS_DHM_C */ |
#if defined(MBEDTLS_ECDH_C) |
"MBEDTLS_ECDH_C", |
#endif /* MBEDTLS_ECDH_C */ |
#if defined(MBEDTLS_ECDSA_C) |
"MBEDTLS_ECDSA_C", |
#endif /* MBEDTLS_ECDSA_C */ |
#if defined(MBEDTLS_ECJPAKE_C) |
"MBEDTLS_ECJPAKE_C", |
#endif /* MBEDTLS_ECJPAKE_C */ |
#if defined(MBEDTLS_ECP_C) |
"MBEDTLS_ECP_C", |
#endif /* MBEDTLS_ECP_C */ |
#if defined(MBEDTLS_ENTROPY_C) |
"MBEDTLS_ENTROPY_C", |
#endif /* MBEDTLS_ENTROPY_C */ |
#if defined(MBEDTLS_ERROR_C) |
"MBEDTLS_ERROR_C", |
#endif /* MBEDTLS_ERROR_C */ |
#if defined(MBEDTLS_GCM_C) |
"MBEDTLS_GCM_C", |
#endif /* MBEDTLS_GCM_C */ |
#if defined(MBEDTLS_HAVEGE_C) |
"MBEDTLS_HAVEGE_C", |
#endif /* MBEDTLS_HAVEGE_C */ |
#if defined(MBEDTLS_HKDF_C) |
"MBEDTLS_HKDF_C", |
#endif /* MBEDTLS_HKDF_C */ |
#if defined(MBEDTLS_HMAC_DRBG_C) |
"MBEDTLS_HMAC_DRBG_C", |
#endif /* MBEDTLS_HMAC_DRBG_C */ |
#if defined(MBEDTLS_NIST_KW_C) |
"MBEDTLS_NIST_KW_C", |
#endif /* MBEDTLS_NIST_KW_C */ |
#if defined(MBEDTLS_MD_C) |
"MBEDTLS_MD_C", |
#endif /* MBEDTLS_MD_C */ |
#if defined(MBEDTLS_MD2_C) |
"MBEDTLS_MD2_C", |
#endif /* MBEDTLS_MD2_C */ |
#if defined(MBEDTLS_MD4_C) |
"MBEDTLS_MD4_C", |
#endif /* MBEDTLS_MD4_C */ |
#if defined(MBEDTLS_MD5_C) |
"MBEDTLS_MD5_C", |
#endif /* MBEDTLS_MD5_C */ |
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) |
"MBEDTLS_MEMORY_BUFFER_ALLOC_C", |
#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ |
#if defined(MBEDTLS_NET_C) |
"MBEDTLS_NET_C", |
#endif /* MBEDTLS_NET_C */ |
#if defined(MBEDTLS_OID_C) |
"MBEDTLS_OID_C", |
#endif /* MBEDTLS_OID_C */ |
#if defined(MBEDTLS_PADLOCK_C) |
"MBEDTLS_PADLOCK_C", |
#endif /* MBEDTLS_PADLOCK_C */ |
#if defined(MBEDTLS_PEM_PARSE_C) |
"MBEDTLS_PEM_PARSE_C", |
#endif /* MBEDTLS_PEM_PARSE_C */ |
#if defined(MBEDTLS_PEM_WRITE_C) |
"MBEDTLS_PEM_WRITE_C", |
#endif /* MBEDTLS_PEM_WRITE_C */ |
#if defined(MBEDTLS_PK_C) |
"MBEDTLS_PK_C", |
#endif /* MBEDTLS_PK_C */ |
#if defined(MBEDTLS_PK_PARSE_C) |
"MBEDTLS_PK_PARSE_C", |
#endif /* MBEDTLS_PK_PARSE_C */ |
#if defined(MBEDTLS_PK_WRITE_C) |
"MBEDTLS_PK_WRITE_C", |
#endif /* MBEDTLS_PK_WRITE_C */ |
#if defined(MBEDTLS_PKCS5_C) |
"MBEDTLS_PKCS5_C", |
#endif /* MBEDTLS_PKCS5_C */ |
#if defined(MBEDTLS_PKCS11_C) |
"MBEDTLS_PKCS11_C", |
#endif /* MBEDTLS_PKCS11_C */ |
#if defined(MBEDTLS_PKCS12_C) |
"MBEDTLS_PKCS12_C", |
#endif /* MBEDTLS_PKCS12_C */ |
#if defined(MBEDTLS_PLATFORM_C) |
"MBEDTLS_PLATFORM_C", |
#endif /* MBEDTLS_PLATFORM_C */ |
#if defined(MBEDTLS_POLY1305_C) |
"MBEDTLS_POLY1305_C", |
#endif /* MBEDTLS_POLY1305_C */ |
#if defined(MBEDTLS_RIPEMD160_C) |
"MBEDTLS_RIPEMD160_C", |
#endif /* MBEDTLS_RIPEMD160_C */ |
#if defined(MBEDTLS_RSA_C) |
"MBEDTLS_RSA_C", |
#endif /* MBEDTLS_RSA_C */ |
#if defined(MBEDTLS_SHA1_C) |
"MBEDTLS_SHA1_C", |
#endif /* MBEDTLS_SHA1_C */ |
#if defined(MBEDTLS_SHA256_C) |
"MBEDTLS_SHA256_C", |
#endif /* MBEDTLS_SHA256_C */ |
#if defined(MBEDTLS_SHA512_C) |
"MBEDTLS_SHA512_C", |
#endif /* MBEDTLS_SHA512_C */ |
#if defined(MBEDTLS_SSL_CACHE_C) |
"MBEDTLS_SSL_CACHE_C", |
#endif /* MBEDTLS_SSL_CACHE_C */ |
#if defined(MBEDTLS_SSL_COOKIE_C) |
"MBEDTLS_SSL_COOKIE_C", |
#endif /* MBEDTLS_SSL_COOKIE_C */ |
#if defined(MBEDTLS_SSL_TICKET_C) |
"MBEDTLS_SSL_TICKET_C", |
#endif /* MBEDTLS_SSL_TICKET_C */ |
#if defined(MBEDTLS_SSL_CLI_C) |
"MBEDTLS_SSL_CLI_C", |
#endif /* MBEDTLS_SSL_CLI_C */ |
#if defined(MBEDTLS_SSL_SRV_C) |
"MBEDTLS_SSL_SRV_C", |
#endif /* MBEDTLS_SSL_SRV_C */ |
#if defined(MBEDTLS_SSL_TLS_C) |
"MBEDTLS_SSL_TLS_C", |
#endif /* MBEDTLS_SSL_TLS_C */ |
#if defined(MBEDTLS_THREADING_C) |
"MBEDTLS_THREADING_C", |
#endif /* MBEDTLS_THREADING_C */ |
#if defined(MBEDTLS_TIMING_C) |
"MBEDTLS_TIMING_C", |
#endif /* MBEDTLS_TIMING_C */ |
#if defined(MBEDTLS_VERSION_C) |
"MBEDTLS_VERSION_C", |
#endif /* MBEDTLS_VERSION_C */ |
#if defined(MBEDTLS_X509_USE_C) |
"MBEDTLS_X509_USE_C", |
#endif /* MBEDTLS_X509_USE_C */ |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
"MBEDTLS_X509_CRT_PARSE_C", |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
#if defined(MBEDTLS_X509_CRL_PARSE_C) |
"MBEDTLS_X509_CRL_PARSE_C", |
#endif /* MBEDTLS_X509_CRL_PARSE_C */ |
#if defined(MBEDTLS_X509_CSR_PARSE_C) |
"MBEDTLS_X509_CSR_PARSE_C", |
#endif /* MBEDTLS_X509_CSR_PARSE_C */ |
#if defined(MBEDTLS_X509_CREATE_C) |
"MBEDTLS_X509_CREATE_C", |
#endif /* MBEDTLS_X509_CREATE_C */ |
#if defined(MBEDTLS_X509_CRT_WRITE_C) |
"MBEDTLS_X509_CRT_WRITE_C", |
#endif /* MBEDTLS_X509_CRT_WRITE_C */ |
#if defined(MBEDTLS_X509_CSR_WRITE_C) |
"MBEDTLS_X509_CSR_WRITE_C", |
#endif /* MBEDTLS_X509_CSR_WRITE_C */ |
#if defined(MBEDTLS_XTEA_C) |
"MBEDTLS_XTEA_C", |
#endif /* MBEDTLS_XTEA_C */ |
#endif /* MBEDTLS_VERSION_FEATURES */ |
NULL |
}; |
int mbedtls_version_check_feature( const char *feature ) |
{ |
const char **idx = features; |
if( *idx == NULL ) |
return( -2 ); |
if( feature == NULL ) |
return( -1 ); |
while( *idx != NULL ) |
{ |
if( !strcmp( *idx, feature ) ) |
return( 0 ); |
idx++; |
} |
return( -1 ); |
} |
#endif /* MBEDTLS_VERSION_C */ |
/programs/develop/libraries/kos_mbedtls/library/x509.c |
---|
0,0 → 1,1074 |
/* |
* X.509 common functions for parsing and verification |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The ITU-T X.509 standard defines a certificate format for PKI. |
* |
* http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) |
* http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) |
* http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) |
* |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_X509_USE_C) |
#include "mbedtls/x509.h" |
#include "mbedtls/asn1.h" |
#include "mbedtls/oid.h" |
#include <stdio.h> |
#include <string.h> |
#if defined(MBEDTLS_PEM_PARSE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#include <stdlib.h> |
#define mbedtls_free free |
#define mbedtls_calloc calloc |
#define mbedtls_printf printf |
#define mbedtls_snprintf snprintf |
#endif |
#if defined(MBEDTLS_HAVE_TIME) |
#include "mbedtls/platform_time.h" |
#endif |
#if defined(MBEDTLS_HAVE_TIME_DATE) |
#include "mbedtls/platform_util.h" |
#include <time.h> |
#endif |
#define CHECK(code) if( ( ret = ( code ) ) != 0 ){ return( ret ); } |
#define CHECK_RANGE(min, max, val) \ |
do \ |
{ \ |
if( ( val ) < ( min ) || ( val ) > ( max ) ) \ |
{ \ |
return( ret ); \ |
} \ |
} while( 0 ) |
/* |
* CertificateSerialNumber ::= INTEGER |
*/ |
int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, |
mbedtls_x509_buf *serial ) |
{ |
int ret; |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_X509_INVALID_SERIAL + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && |
**p != MBEDTLS_ASN1_INTEGER ) |
return( MBEDTLS_ERR_X509_INVALID_SERIAL + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
serial->tag = *(*p)++; |
if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); |
serial->p = *p; |
*p += serial->len; |
return( 0 ); |
} |
/* Get an algorithm identifier without parameters (eg for signatures) |
* |
* AlgorithmIdentifier ::= SEQUENCE { |
* algorithm OBJECT IDENTIFIER, |
* parameters ANY DEFINED BY algorithm OPTIONAL } |
*/ |
int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, |
mbedtls_x509_buf *alg ) |
{ |
int ret; |
if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
return( 0 ); |
} |
/* |
* Parse an algorithm identifier with (optional) parameters |
*/ |
int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, |
mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) |
{ |
int ret; |
if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
return( 0 ); |
} |
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
/* |
* HashAlgorithm ::= AlgorithmIdentifier |
* |
* AlgorithmIdentifier ::= SEQUENCE { |
* algorithm OBJECT IDENTIFIER, |
* parameters ANY DEFINED BY algorithm OPTIONAL } |
* |
* For HashAlgorithm, parameters MUST be NULL or absent. |
*/ |
static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) |
{ |
int ret; |
unsigned char *p; |
const unsigned char *end; |
mbedtls_x509_buf md_oid; |
size_t len; |
/* Make sure we got a SEQUENCE and setup bounds */ |
if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
p = (unsigned char *) alg->p; |
end = p + alg->len; |
if( p >= end ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
/* Parse md_oid */ |
md_oid.tag = *p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
md_oid.p = p; |
p += md_oid.len; |
/* Get md_alg from md_oid */ |
if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
/* Make sure params is absent of NULL */ |
if( p == end ) |
return( 0 ); |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p != end ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* RSASSA-PSS-params ::= SEQUENCE { |
* hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, |
* maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, |
* saltLength [2] INTEGER DEFAULT 20, |
* trailerField [3] INTEGER DEFAULT 1 } |
* -- Note that the tags in this Sequence are explicit. |
* |
* RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value |
* of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other |
* option. Enfore this at parsing time. |
*/ |
int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, |
mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, |
int *salt_len ) |
{ |
int ret; |
unsigned char *p; |
const unsigned char *end, *end2; |
size_t len; |
mbedtls_x509_buf alg_id, alg_params; |
/* First set everything to defaults */ |
*md_alg = MBEDTLS_MD_SHA1; |
*mgf_md = MBEDTLS_MD_SHA1; |
*salt_len = 20; |
/* Make sure params is a SEQUENCE and setup bounds */ |
if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
p = (unsigned char *) params->p; |
end = p + params->len; |
if( p == end ) |
return( 0 ); |
/* |
* HashAlgorithm |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) |
{ |
end2 = p + len; |
/* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ |
if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p != end2 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p == end ) |
return( 0 ); |
/* |
* MaskGenAlgorithm |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) |
{ |
end2 = p + len; |
/* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ |
if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) |
return( ret ); |
/* Only MFG1 is recognised for now */ |
if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) |
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + |
MBEDTLS_ERR_OID_NOT_FOUND ); |
/* Parse HashAlgorithm */ |
if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) |
return( ret ); |
if( p != end2 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p == end ) |
return( 0 ); |
/* |
* salt_len |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) |
{ |
end2 = p + len; |
if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p != end2 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p == end ) |
return( 0 ); |
/* |
* trailer_field (if present, must be 1) |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) |
{ |
int trailer_field; |
end2 = p + len; |
if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p != end2 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
if( trailer_field != 1 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG ); |
} |
else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); |
if( p != end ) |
return( MBEDTLS_ERR_X509_INVALID_ALG + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ |
/* |
* AttributeTypeAndValue ::= SEQUENCE { |
* type AttributeType, |
* value AttributeValue } |
* |
* AttributeType ::= OBJECT IDENTIFIER |
* |
* AttributeValue ::= ANY DEFINED BY AttributeType |
*/ |
static int x509_get_attr_type_value( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_name *cur ) |
{ |
int ret; |
size_t len; |
mbedtls_x509_buf *oid; |
mbedtls_x509_buf *val; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); |
end = *p + len; |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_X509_INVALID_NAME + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
oid = &cur->oid; |
oid->tag = **p; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); |
oid->p = *p; |
*p += oid->len; |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_X509_INVALID_NAME + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && |
**p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && |
**p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && |
**p != MBEDTLS_ASN1_BIT_STRING ) |
return( MBEDTLS_ERR_X509_INVALID_NAME + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
val = &cur->val; |
val->tag = *(*p)++; |
if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); |
val->p = *p; |
*p += val->len; |
if( *p != end ) |
{ |
return( MBEDTLS_ERR_X509_INVALID_NAME + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
cur->next = NULL; |
return( 0 ); |
} |
/* |
* Name ::= CHOICE { -- only one possibility for now -- |
* rdnSequence RDNSequence } |
* |
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName |
* |
* RelativeDistinguishedName ::= |
* SET OF AttributeTypeAndValue |
* |
* AttributeTypeAndValue ::= SEQUENCE { |
* type AttributeType, |
* value AttributeValue } |
* |
* AttributeType ::= OBJECT IDENTIFIER |
* |
* AttributeValue ::= ANY DEFINED BY AttributeType |
* |
* The data structure is optimized for the common case where each RDN has only |
* one element, which is represented as a list of AttributeTypeAndValue. |
* For the general case we still use a flat list, but we mark elements of the |
* same set so that they are "merged" together in the functions that consume |
* this list, eg mbedtls_x509_dn_gets(). |
*/ |
int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, |
mbedtls_x509_name *cur ) |
{ |
int ret; |
size_t set_len; |
const unsigned char *end_set; |
/* don't use recursion, we'd risk stack overflow if not optimized */ |
while( 1 ) |
{ |
/* |
* parse SET |
*/ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); |
end_set = *p + set_len; |
while( 1 ) |
{ |
if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) |
return( ret ); |
if( *p == end_set ) |
break; |
/* Mark this item as being no the only one in a set */ |
cur->next_merged = 1; |
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); |
if( cur->next == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
cur = cur->next; |
} |
/* |
* continue until end of SEQUENCE is reached |
*/ |
if( *p == end ) |
return( 0 ); |
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); |
if( cur->next == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
cur = cur->next; |
} |
} |
static int x509_parse_int( unsigned char **p, size_t n, int *res ) |
{ |
*res = 0; |
for( ; n > 0; --n ) |
{ |
if( ( **p < '0') || ( **p > '9' ) ) |
return ( MBEDTLS_ERR_X509_INVALID_DATE ); |
*res *= 10; |
*res += ( *(*p)++ - '0' ); |
} |
return( 0 ); |
} |
static int x509_date_is_valid(const mbedtls_x509_time *t ) |
{ |
int ret = MBEDTLS_ERR_X509_INVALID_DATE; |
int month_len; |
CHECK_RANGE( 0, 9999, t->year ); |
CHECK_RANGE( 0, 23, t->hour ); |
CHECK_RANGE( 0, 59, t->min ); |
CHECK_RANGE( 0, 59, t->sec ); |
switch( t->mon ) |
{ |
case 1: case 3: case 5: case 7: case 8: case 10: case 12: |
month_len = 31; |
break; |
case 4: case 6: case 9: case 11: |
month_len = 30; |
break; |
case 2: |
if( ( !( t->year % 4 ) && t->year % 100 ) || |
!( t->year % 400 ) ) |
month_len = 29; |
else |
month_len = 28; |
break; |
default: |
return( ret ); |
} |
CHECK_RANGE( 1, month_len, t->day ); |
return( 0 ); |
} |
/* |
* Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) |
* field. |
*/ |
static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, |
mbedtls_x509_time *tm ) |
{ |
int ret; |
/* |
* Minimum length is 10 or 12 depending on yearlen |
*/ |
if ( len < yearlen + 8 ) |
return ( MBEDTLS_ERR_X509_INVALID_DATE ); |
len -= yearlen + 8; |
/* |
* Parse year, month, day, hour, minute |
*/ |
CHECK( x509_parse_int( p, yearlen, &tm->year ) ); |
if ( 2 == yearlen ) |
{ |
if ( tm->year < 50 ) |
tm->year += 100; |
tm->year += 1900; |
} |
CHECK( x509_parse_int( p, 2, &tm->mon ) ); |
CHECK( x509_parse_int( p, 2, &tm->day ) ); |
CHECK( x509_parse_int( p, 2, &tm->hour ) ); |
CHECK( x509_parse_int( p, 2, &tm->min ) ); |
/* |
* Parse seconds if present |
*/ |
if ( len >= 2 ) |
{ |
CHECK( x509_parse_int( p, 2, &tm->sec ) ); |
len -= 2; |
} |
else |
return ( MBEDTLS_ERR_X509_INVALID_DATE ); |
/* |
* Parse trailing 'Z' if present |
*/ |
if ( 1 == len && 'Z' == **p ) |
{ |
(*p)++; |
len--; |
} |
/* |
* We should have parsed all characters at this point |
*/ |
if ( 0 != len ) |
return ( MBEDTLS_ERR_X509_INVALID_DATE ); |
CHECK( x509_date_is_valid( tm ) ); |
return ( 0 ); |
} |
/* |
* Time ::= CHOICE { |
* utcTime UTCTime, |
* generalTime GeneralizedTime } |
*/ |
int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, |
mbedtls_x509_time *tm ) |
{ |
int ret; |
size_t len, year_len; |
unsigned char tag; |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_X509_INVALID_DATE + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
tag = **p; |
if( tag == MBEDTLS_ASN1_UTC_TIME ) |
year_len = 2; |
else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) |
year_len = 4; |
else |
return( MBEDTLS_ERR_X509_INVALID_DATE + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
(*p)++; |
ret = mbedtls_asn1_get_len( p, end, &len ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); |
return x509_parse_time( p, len, year_len, tm ); |
} |
int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) |
{ |
int ret; |
size_t len; |
int tag_type; |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
tag_type = **p; |
if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); |
sig->tag = tag_type; |
sig->len = len; |
sig->p = *p; |
*p += len; |
return( 0 ); |
} |
/* |
* Get signature algorithm from alg OID and optional parameters |
*/ |
int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, |
mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, |
void **sig_opts ) |
{ |
int ret; |
if( *sig_opts != NULL ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) |
return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); |
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) |
{ |
mbedtls_pk_rsassa_pss_options *pss_opts; |
pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); |
if( pss_opts == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
ret = mbedtls_x509_get_rsassa_pss_params( sig_params, |
md_alg, |
&pss_opts->mgf1_hash_id, |
&pss_opts->expected_salt_len ); |
if( ret != 0 ) |
{ |
mbedtls_free( pss_opts ); |
return( ret ); |
} |
*sig_opts = (void *) pss_opts; |
} |
else |
#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ |
{ |
/* Make sure parameters are absent or NULL */ |
if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || |
sig_params->len != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_ALG ); |
} |
return( 0 ); |
} |
/* |
* X.509 Extensions (No parsing of extensions, pointer should |
* be either manually updated or extensions should be parsed!) |
*/ |
int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, |
mbedtls_x509_buf *ext, int tag ) |
{ |
int ret; |
size_t len; |
/* Extension structure use EXPLICIT tagging. That is, the actual |
* `Extensions` structure is wrapped by a tag-length pair using |
* the respective context-specific tag. */ |
ret = mbedtls_asn1_get_tag( p, end, &ext->len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; |
ext->p = *p; |
end = *p + ext->len; |
/* |
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
*/ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( end != *p + len ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* Store the name in printable form into buf; no more |
* than size characters will be written |
*/ |
int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) |
{ |
int ret; |
size_t i, n; |
unsigned char c, merge = 0; |
const mbedtls_x509_name *name; |
const char *short_name = NULL; |
char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; |
memset( s, 0, sizeof( s ) ); |
name = dn; |
p = buf; |
n = size; |
while( name != NULL ) |
{ |
if( !name->oid.p ) |
{ |
name = name->next; |
continue; |
} |
if( name != dn ) |
{ |
ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
} |
ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); |
if( ret == 0 ) |
ret = mbedtls_snprintf( p, n, "%s=", short_name ); |
else |
ret = mbedtls_snprintf( p, n, "\?\?=" ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
for( i = 0; i < name->val.len; i++ ) |
{ |
if( i >= sizeof( s ) - 1 ) |
break; |
c = name->val.p[i]; |
if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) |
s[i] = '?'; |
else s[i] = c; |
} |
s[i] = '\0'; |
ret = mbedtls_snprintf( p, n, "%s", s ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
merge = name->next_merged; |
name = name->next; |
} |
return( (int) ( size - n ) ); |
} |
/* |
* Store the serial in printable form into buf; no more |
* than size characters will be written |
*/ |
int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) |
{ |
int ret; |
size_t i, n, nr; |
char *p; |
p = buf; |
n = size; |
nr = ( serial->len <= 32 ) |
? serial->len : 28; |
for( i = 0; i < nr; i++ ) |
{ |
if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) |
continue; |
ret = mbedtls_snprintf( p, n, "%02X%s", |
serial->p[i], ( i < nr - 1 ) ? ":" : "" ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
} |
if( nr != serial->len ) |
{ |
ret = mbedtls_snprintf( p, n, "...." ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
} |
return( (int) ( size - n ) ); |
} |
/* |
* Helper for writing signature algorithms |
*/ |
int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, |
mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, |
const void *sig_opts ) |
{ |
int ret; |
char *p = buf; |
size_t n = size; |
const char *desc = NULL; |
ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); |
if( ret != 0 ) |
ret = mbedtls_snprintf( p, n, "???" ); |
else |
ret = mbedtls_snprintf( p, n, "%s", desc ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) |
{ |
const mbedtls_pk_rsassa_pss_options *pss_opts; |
const mbedtls_md_info_t *md_info, *mgf_md_info; |
pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; |
md_info = mbedtls_md_info_from_type( md_alg ); |
mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); |
ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", |
md_info ? mbedtls_md_get_name( md_info ) : "???", |
mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", |
pss_opts->expected_salt_len ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
} |
#else |
((void) pk_alg); |
((void) md_alg); |
((void) sig_opts); |
#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ |
return( (int)( size - n ) ); |
} |
/* |
* Helper for writing "RSA key size", "EC key size", etc |
*/ |
int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) |
{ |
char *p = buf; |
size_t n = buf_size; |
int ret; |
ret = mbedtls_snprintf( p, n, "%s key size", name ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
return( 0 ); |
} |
#if defined(MBEDTLS_HAVE_TIME_DATE) |
/* |
* Set the time structure to the current time. |
* Return 0 on success, non-zero on failure. |
*/ |
static int x509_get_current_time( mbedtls_x509_time *now ) |
{ |
struct tm *lt, tm_buf; |
mbedtls_time_t tt; |
int ret = 0; |
tt = mbedtls_time( NULL ); |
lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); |
if( lt == NULL ) |
ret = -1; |
else |
{ |
now->year = lt->tm_year + 1900; |
now->mon = lt->tm_mon + 1; |
now->day = lt->tm_mday; |
now->hour = lt->tm_hour; |
now->min = lt->tm_min; |
now->sec = lt->tm_sec; |
} |
return( ret ); |
} |
/* |
* Return 0 if before <= after, 1 otherwise |
*/ |
static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) |
{ |
if( before->year > after->year ) |
return( 1 ); |
if( before->year == after->year && |
before->mon > after->mon ) |
return( 1 ); |
if( before->year == after->year && |
before->mon == after->mon && |
before->day > after->day ) |
return( 1 ); |
if( before->year == after->year && |
before->mon == after->mon && |
before->day == after->day && |
before->hour > after->hour ) |
return( 1 ); |
if( before->year == after->year && |
before->mon == after->mon && |
before->day == after->day && |
before->hour == after->hour && |
before->min > after->min ) |
return( 1 ); |
if( before->year == after->year && |
before->mon == after->mon && |
before->day == after->day && |
before->hour == after->hour && |
before->min == after->min && |
before->sec > after->sec ) |
return( 1 ); |
return( 0 ); |
} |
int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) |
{ |
mbedtls_x509_time now; |
if( x509_get_current_time( &now ) != 0 ) |
return( 1 ); |
return( x509_check_time( &now, to ) ); |
} |
int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) |
{ |
mbedtls_x509_time now; |
if( x509_get_current_time( &now ) != 0 ) |
return( 1 ); |
return( x509_check_time( from, &now ) ); |
} |
#else /* MBEDTLS_HAVE_TIME_DATE */ |
int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) |
{ |
((void) to); |
return( 0 ); |
} |
int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) |
{ |
((void) from); |
return( 0 ); |
} |
#endif /* MBEDTLS_HAVE_TIME_DATE */ |
#if defined(MBEDTLS_SELF_TEST) |
#include "mbedtls/x509_crt.h" |
#include "mbedtls/certs.h" |
/* |
* Checkup routine |
*/ |
int mbedtls_x509_self_test( int verbose ) |
{ |
int ret = 0; |
#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) |
uint32_t flags; |
mbedtls_x509_crt cacert; |
mbedtls_x509_crt clicert; |
if( verbose != 0 ) |
mbedtls_printf( " X.509 certificate load: " ); |
mbedtls_x509_crt_init( &cacert ); |
mbedtls_x509_crt_init( &clicert ); |
ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, |
mbedtls_test_cli_crt_len ); |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
goto cleanup; |
} |
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, |
mbedtls_test_ca_crt_len ); |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n X.509 signature verify: "); |
ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); |
if( ret != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
goto cleanup; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n\n"); |
cleanup: |
mbedtls_x509_crt_free( &cacert ); |
mbedtls_x509_crt_free( &clicert ); |
#else |
((void) verbose); |
#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */ |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_X509_USE_C */ |
/programs/develop/libraries/kos_mbedtls/library/x509_create.c |
---|
0,0 → 1,381 |
/* |
* X.509 base functions for creating certificates / CSRs |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_X509_CREATE_C) |
#include "mbedtls/x509.h" |
#include "mbedtls/asn1write.h" |
#include "mbedtls/oid.h" |
#include <string.h> |
/* Structure linking OIDs for X.509 DN AttributeTypes to their |
* string representations and default string encodings used by Mbed TLS. */ |
typedef struct { |
const char *name; /* String representation of AttributeType, e.g. |
* "CN" or "emailAddress". */ |
size_t name_len; /* Length of 'name', without trailing 0 byte. */ |
const char *oid; /* String representation of OID of AttributeType, |
* as per RFC 5280, Appendix A.1. */ |
int default_tag; /* The default character encoding used for the |
* given attribute type, e.g. |
* MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ |
} x509_attr_descriptor_t; |
#define ADD_STRLEN( s ) s, sizeof( s ) - 1 |
/* X.509 DN attributes from RFC 5280, Appendix A.1. */ |
static const x509_attr_descriptor_t x509_attrs[] = |
{ |
{ ADD_STRLEN( "CN" ), |
MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "commonName" ), |
MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "C" ), |
MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, |
{ ADD_STRLEN( "countryName" ), |
MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, |
{ ADD_STRLEN( "O" ), |
MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "organizationName" ), |
MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "L" ), |
MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "locality" ), |
MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "R" ), |
MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, |
{ ADD_STRLEN( "OU" ), |
MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "organizationalUnitName" ), |
MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "ST" ), |
MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "stateOrProvinceName" ), |
MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "emailAddress" ), |
MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, |
{ ADD_STRLEN( "serialNumber" ), |
MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, |
{ ADD_STRLEN( "postalAddress" ), |
MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, |
{ ADD_STRLEN( "postalCode" ), |
MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, |
{ ADD_STRLEN( "dnQualifier" ), |
MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, |
{ ADD_STRLEN( "title" ), |
MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "surName" ), |
MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "SN" ), |
MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "givenName" ), |
MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "GN" ), |
MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "initials" ), |
MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "pseudonym" ), |
MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "generationQualifier" ), |
MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, |
{ ADD_STRLEN( "domainComponent" ), |
MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, |
{ ADD_STRLEN( "DC" ), |
MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, |
{ NULL, 0, NULL, MBEDTLS_ASN1_NULL } |
}; |
static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) |
{ |
const x509_attr_descriptor_t *cur; |
for( cur = x509_attrs; cur->name != NULL; cur++ ) |
if( cur->name_len == name_len && |
strncmp( cur->name, name, name_len ) == 0 ) |
break; |
if ( cur->name == NULL ) |
return( NULL ); |
return( cur ); |
} |
int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) |
{ |
int ret = 0; |
const char *s = name, *c = s; |
const char *end = s + strlen( s ); |
const char *oid = NULL; |
const x509_attr_descriptor_t* attr_descr = NULL; |
int in_tag = 1; |
char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; |
char *d = data; |
/* Clear existing chain if present */ |
mbedtls_asn1_free_named_data_list( head ); |
while( c <= end ) |
{ |
if( in_tag && *c == '=' ) |
{ |
if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) |
{ |
ret = MBEDTLS_ERR_X509_UNKNOWN_OID; |
goto exit; |
} |
oid = attr_descr->oid; |
s = c + 1; |
in_tag = 0; |
d = data; |
} |
if( !in_tag && *c == '\\' && c != end ) |
{ |
c++; |
/* Check for valid escaped characters */ |
if( c == end || *c != ',' ) |
{ |
ret = MBEDTLS_ERR_X509_INVALID_NAME; |
goto exit; |
} |
} |
else if( !in_tag && ( *c == ',' || c == end ) ) |
{ |
mbedtls_asn1_named_data* cur = |
mbedtls_asn1_store_named_data( head, oid, strlen( oid ), |
(unsigned char *) data, |
d - data ); |
if(cur == NULL ) |
{ |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
} |
// set tagType |
cur->val.tag = attr_descr->default_tag; |
while( c < end && *(c + 1) == ' ' ) |
c++; |
s = c + 1; |
in_tag = 1; |
} |
if( !in_tag && s != c + 1 ) |
{ |
*(d++) = *c; |
if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) |
{ |
ret = MBEDTLS_ERR_X509_INVALID_NAME; |
goto exit; |
} |
} |
c++; |
} |
exit: |
return( ret ); |
} |
/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved |
* to store the critical boolean for us |
*/ |
int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, |
int critical, const unsigned char *val, size_t val_len ) |
{ |
mbedtls_asn1_named_data *cur; |
if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, |
NULL, val_len + 1 ) ) == NULL ) |
{ |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
} |
cur->val.p[0] = critical; |
memcpy( cur->val.p + 1, val, val_len ); |
return( 0 ); |
} |
/* |
* RelativeDistinguishedName ::= |
* SET OF AttributeTypeAndValue |
* |
* AttributeTypeAndValue ::= SEQUENCE { |
* type AttributeType, |
* value AttributeValue } |
* |
* AttributeType ::= OBJECT IDENTIFIER |
* |
* AttributeValue ::= ANY DEFINED BY AttributeType |
*/ |
static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) |
{ |
int ret; |
size_t len = 0; |
const char *oid = (const char*)cur_name->oid.p; |
size_t oid_len = cur_name->oid.len; |
const unsigned char *name = cur_name->val.p; |
size_t name_len = cur_name->val.len; |
// Write correct string tag and value |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, |
cur_name->val.tag, |
(const char *) name, |
name_len ) ); |
// Write OID |
// |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, |
oid_len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, |
MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, |
MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SET ) ); |
return( (int) len ); |
} |
int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, |
mbedtls_asn1_named_data *first ) |
{ |
int ret; |
size_t len = 0; |
mbedtls_asn1_named_data *cur = first; |
while( cur != NULL ) |
{ |
MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); |
cur = cur->next; |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return( (int) len ); |
} |
int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, |
const char *oid, size_t oid_len, |
unsigned char *sig, size_t size ) |
{ |
int ret; |
size_t len = 0; |
if( *p < start || (size_t)( *p - start ) < size ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
len = size; |
(*p) -= len; |
memcpy( *p, sig, len ); |
if( *p - start < 1 ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
*--(*p) = 0; |
len += 1; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); |
// Write OID |
// |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, |
oid_len, 0 ) ); |
return( (int) len ); |
} |
static int x509_write_extension( unsigned char **p, unsigned char *start, |
mbedtls_asn1_named_data *ext ) |
{ |
int ret; |
size_t len = 0; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, |
ext->val.len - 1 ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); |
if( ext->val.p[0] != 0 ) |
{ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, |
ext->oid.len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return( (int) len ); |
} |
/* |
* Extension ::= SEQUENCE { |
* extnID OBJECT IDENTIFIER, |
* critical BOOLEAN DEFAULT FALSE, |
* extnValue OCTET STRING |
* -- contains the DER encoding of an ASN.1 value |
* -- corresponding to the extension type identified |
* -- by extnID |
* } |
*/ |
int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, |
mbedtls_asn1_named_data *first ) |
{ |
int ret; |
size_t len = 0; |
mbedtls_asn1_named_data *cur_ext = first; |
while( cur_ext != NULL ) |
{ |
MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); |
cur_ext = cur_ext->next; |
} |
return( (int) len ); |
} |
#endif /* MBEDTLS_X509_CREATE_C */ |
/programs/develop/libraries/kos_mbedtls/library/x509_crl.c |
---|
0,0 → 1,775 |
/* |
* X.509 Certidicate Revocation List (CRL) parsing |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The ITU-T X.509 standard defines a certificate format for PKI. |
* |
* http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) |
* http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) |
* http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) |
* |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_X509_CRL_PARSE_C) |
#include "mbedtls/x509_crl.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PEM_PARSE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#include <stdio.h> |
#define mbedtls_free free |
#define mbedtls_calloc calloc |
#define mbedtls_snprintf snprintf |
#endif |
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) |
#include <windows.h> |
#else |
#include <time.h> |
#endif |
#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) |
#include <stdio.h> |
#endif |
/* |
* Version ::= INTEGER { v1(0), v2(1) } |
*/ |
static int x509_crl_get_version( unsigned char **p, |
const unsigned char *end, |
int *ver ) |
{ |
int ret; |
if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
{ |
*ver = 0; |
return( 0 ); |
} |
return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); |
} |
return( 0 ); |
} |
/* |
* X.509 CRL v2 extensions |
* |
* We currently don't parse any extension's content, but we do check that the |
* list of extensions is well-formed and abort on critical extensions (that |
* are unsupported as we don't support any extension so far) |
*/ |
static int x509_get_crl_ext( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_buf *ext ) |
{ |
int ret; |
if( *p == end ) |
return( 0 ); |
/* |
* crlExtensions [0] EXPLICIT Extensions OPTIONAL |
* -- if present, version MUST be v2 |
*/ |
if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) |
return( ret ); |
end = ext->p + ext->len; |
while( *p < end ) |
{ |
/* |
* Extension ::= SEQUENCE { |
* extnID OBJECT IDENTIFIER, |
* critical BOOLEAN DEFAULT FALSE, |
* extnValue OCTET STRING } |
*/ |
int is_critical = 0; |
const unsigned char *end_ext_data; |
size_t len; |
/* Get enclosing sequence tag */ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
end_ext_data = *p + len; |
/* Get OID (currently ignored) */ |
if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, |
MBEDTLS_ASN1_OID ) ) != 0 ) |
{ |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
} |
*p += len; |
/* Get optional critical */ |
if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, |
&is_critical ) ) != 0 && |
( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) |
{ |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
} |
/* Data should be octet string type */ |
if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, |
MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
/* Ignore data so far and just check its length */ |
*p += len; |
if( *p != end_ext_data ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
/* Abort on (unsupported) critical extensions */ |
if( is_critical ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
} |
if( *p != end ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* X.509 CRL v2 entry extensions (no extensions parsed yet.) |
*/ |
static int x509_get_crl_entry_ext( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_buf *ext ) |
{ |
int ret; |
size_t len = 0; |
/* OPTIONAL */ |
if( end <= *p ) |
return( 0 ); |
ext->tag = **p; |
ext->p = *p; |
/* |
* Get CRL-entry extension sequence header |
* crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 |
*/ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
{ |
ext->p = NULL; |
return( 0 ); |
} |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
} |
end = *p + ext->len; |
if( end != *p + ext->len ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
while( *p < end ) |
{ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
*p += len; |
} |
if( *p != end ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* X.509 CRL Entries |
*/ |
static int x509_get_entries( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_crl_entry *entry ) |
{ |
int ret; |
size_t entry_len; |
mbedtls_x509_crl_entry *cur_entry = entry; |
if( *p == end ) |
return( 0 ); |
if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, |
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
return( 0 ); |
return( ret ); |
} |
end = *p + entry_len; |
while( *p < end ) |
{ |
size_t len2; |
const unsigned char *end2; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, |
MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) |
{ |
return( ret ); |
} |
cur_entry->raw.tag = **p; |
cur_entry->raw.p = *p; |
cur_entry->raw.len = len2; |
end2 = *p + len2; |
if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_x509_get_time( p, end2, |
&cur_entry->revocation_date ) ) != 0 ) |
return( ret ); |
if( ( ret = x509_get_crl_entry_ext( p, end2, |
&cur_entry->entry_ext ) ) != 0 ) |
return( ret ); |
if( *p < end ) |
{ |
cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); |
if( cur_entry->next == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
cur_entry = cur_entry->next; |
} |
} |
return( 0 ); |
} |
/* |
* Parse one CRLs in DER format and append it to the chained list |
*/ |
int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, |
const unsigned char *buf, size_t buflen ) |
{ |
int ret; |
size_t len; |
unsigned char *p = NULL, *end = NULL; |
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; |
mbedtls_x509_crl *crl = chain; |
/* |
* Check for valid input |
*/ |
if( crl == NULL || buf == NULL ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); |
memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); |
memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); |
/* |
* Add new CRL on the end of the chain if needed. |
*/ |
while( crl->version != 0 && crl->next != NULL ) |
crl = crl->next; |
if( crl->version != 0 && crl->next == NULL ) |
{ |
crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); |
if( crl->next == NULL ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
} |
mbedtls_x509_crl_init( crl->next ); |
crl = crl->next; |
} |
/* |
* Copy raw DER-encoded CRL |
*/ |
if( buflen == 0 ) |
return( MBEDTLS_ERR_X509_INVALID_FORMAT ); |
p = mbedtls_calloc( 1, buflen ); |
if( p == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
memcpy( p, buf, buflen ); |
crl->raw.p = p; |
crl->raw.len = buflen; |
end = p + buflen; |
/* |
* CertificateList ::= SEQUENCE { |
* tbsCertList TBSCertList, |
* signatureAlgorithm AlgorithmIdentifier, |
* signatureValue BIT STRING } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT ); |
} |
if( len != (size_t) ( end - p ) ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
/* |
* TBSCertList ::= SEQUENCE { |
*/ |
crl->tbs.p = p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
end = p + len; |
crl->tbs.len = end - crl->tbs.p; |
/* |
* Version ::= INTEGER OPTIONAL { v1(0), v2(1) } |
* -- if present, MUST be v2 |
* |
* signature AlgorithmIdentifier |
*/ |
if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || |
( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
if( crl->version < 0 || crl->version > 1 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); |
} |
crl->version++; |
if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, |
&crl->sig_md, &crl->sig_pk, |
&crl->sig_opts ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); |
} |
/* |
* issuer Name |
*/ |
crl->issuer_raw.p = p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
crl->issuer_raw.len = p - crl->issuer_raw.p; |
/* |
* thisUpdate Time |
* nextUpdate Time OPTIONAL |
*/ |
if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) |
{ |
if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && |
ret != ( MBEDTLS_ERR_X509_INVALID_DATE + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
} |
/* |
* revokedCertificates SEQUENCE OF SEQUENCE { |
* userCertificate CertificateSerialNumber, |
* revocationDate Time, |
* crlEntryExtensions Extensions OPTIONAL |
* -- if present, MUST be v2 |
* } OPTIONAL |
*/ |
if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
/* |
* crlExtensions EXPLICIT Extensions OPTIONAL |
* -- if present, MUST be v2 |
*/ |
if( crl->version == 2 ) |
{ |
ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); |
if( ret != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
} |
if( p != end ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
end = crl->raw.p + crl->raw.len; |
/* |
* signatureAlgorithm AlgorithmIdentifier, |
* signatureValue BIT STRING |
*/ |
if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
if( crl->sig_oid.len != sig_oid2.len || |
memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || |
sig_params1.len != sig_params2.len || |
( sig_params1.len != 0 && |
memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_SIG_MISMATCH ); |
} |
if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( ret ); |
} |
if( p != end ) |
{ |
mbedtls_x509_crl_free( crl ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
return( 0 ); |
} |
/* |
* Parse one or more CRLs and add them to the chained list |
*/ |
int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) |
{ |
#if defined(MBEDTLS_PEM_PARSE_C) |
int ret; |
size_t use_len; |
mbedtls_pem_context pem; |
int is_pem = 0; |
if( chain == NULL || buf == NULL ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
do |
{ |
mbedtls_pem_init( &pem ); |
// Avoid calling mbedtls_pem_read_buffer() on non-null-terminated |
// string |
if( buflen == 0 || buf[buflen - 1] != '\0' ) |
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; |
else |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN X509 CRL-----", |
"-----END X509 CRL-----", |
buf, NULL, 0, &use_len ); |
if( ret == 0 ) |
{ |
/* |
* Was PEM encoded |
*/ |
is_pem = 1; |
buflen -= use_len; |
buf += use_len; |
if( ( ret = mbedtls_x509_crl_parse_der( chain, |
pem.buf, pem.buflen ) ) != 0 ) |
{ |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
} |
else if( is_pem ) |
{ |
mbedtls_pem_free( &pem ); |
return( ret ); |
} |
mbedtls_pem_free( &pem ); |
} |
/* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. |
* And a valid CRL cannot be less than 1 byte anyway. */ |
while( is_pem && buflen > 1 ); |
if( is_pem ) |
return( 0 ); |
else |
#endif /* MBEDTLS_PEM_PARSE_C */ |
return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); |
} |
#if defined(MBEDTLS_FS_IO) |
/* |
* Load one or more CRLs and add them to the chained list |
*/ |
int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) |
{ |
int ret; |
size_t n; |
unsigned char *buf; |
if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) |
return( ret ); |
ret = mbedtls_x509_crl_parse( chain, buf, n ); |
mbedtls_platform_zeroize( buf, n ); |
mbedtls_free( buf ); |
return( ret ); |
} |
#endif /* MBEDTLS_FS_IO */ |
/* |
* Return an informational string about the certificate. |
*/ |
#define BEFORE_COLON 14 |
#define BC "14" |
/* |
* Return an informational string about the CRL. |
*/ |
int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, |
const mbedtls_x509_crl *crl ) |
{ |
int ret; |
size_t n; |
char *p; |
const mbedtls_x509_crl_entry *entry; |
p = buf; |
n = size; |
ret = mbedtls_snprintf( p, n, "%sCRL version : %d", |
prefix, crl->version ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ |
"%04d-%02d-%02d %02d:%02d:%02d", prefix, |
crl->this_update.year, crl->this_update.mon, |
crl->this_update.day, crl->this_update.hour, |
crl->this_update.min, crl->this_update.sec ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%snext update : " \ |
"%04d-%02d-%02d %02d:%02d:%02d", prefix, |
crl->next_update.year, crl->next_update.mon, |
crl->next_update.day, crl->next_update.hour, |
crl->next_update.min, crl->next_update.sec ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
entry = &crl->entry; |
ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", |
prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
while( entry != NULL && entry->raw.len != 0 ) |
{ |
ret = mbedtls_snprintf( p, n, "\n%sserial number: ", |
prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, " revocation date: " \ |
"%04d-%02d-%02d %02d:%02d:%02d", |
entry->revocation_date.year, entry->revocation_date.mon, |
entry->revocation_date.day, entry->revocation_date.hour, |
entry->revocation_date.min, entry->revocation_date.sec ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
entry = entry->next; |
} |
ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, |
crl->sig_opts ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n" ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
return( (int) ( size - n ) ); |
} |
/* |
* Initialize a CRL chain |
*/ |
void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) |
{ |
memset( crl, 0, sizeof(mbedtls_x509_crl) ); |
} |
/* |
* Unallocate all CRL data |
*/ |
void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) |
{ |
mbedtls_x509_crl *crl_cur = crl; |
mbedtls_x509_crl *crl_prv; |
mbedtls_x509_name *name_cur; |
mbedtls_x509_name *name_prv; |
mbedtls_x509_crl_entry *entry_cur; |
mbedtls_x509_crl_entry *entry_prv; |
if( crl == NULL ) |
return; |
do |
{ |
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
mbedtls_free( crl_cur->sig_opts ); |
#endif |
name_cur = crl_cur->issuer.next; |
while( name_cur != NULL ) |
{ |
name_prv = name_cur; |
name_cur = name_cur->next; |
mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); |
mbedtls_free( name_prv ); |
} |
entry_cur = crl_cur->entry.next; |
while( entry_cur != NULL ) |
{ |
entry_prv = entry_cur; |
entry_cur = entry_cur->next; |
mbedtls_platform_zeroize( entry_prv, |
sizeof( mbedtls_x509_crl_entry ) ); |
mbedtls_free( entry_prv ); |
} |
if( crl_cur->raw.p != NULL ) |
{ |
mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); |
mbedtls_free( crl_cur->raw.p ); |
} |
crl_cur = crl_cur->next; |
} |
while( crl_cur != NULL ); |
crl_cur = crl; |
do |
{ |
crl_prv = crl_cur; |
crl_cur = crl_cur->next; |
mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); |
if( crl_prv != crl ) |
mbedtls_free( crl_prv ); |
} |
while( crl_cur != NULL ); |
} |
#endif /* MBEDTLS_X509_CRL_PARSE_C */ |
/programs/develop/libraries/kos_mbedtls/library/x509_crt.c |
---|
0,0 → 1,2732 |
/* |
* X.509 certificate parsing and verification |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The ITU-T X.509 standard defines a certificate format for PKI. |
* |
* http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) |
* http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) |
* http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) |
* |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf |
* |
* [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_X509_CRT_PARSE_C) |
#include "mbedtls/x509_crt.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PEM_PARSE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#include <stdlib.h> |
#define mbedtls_free free |
#define mbedtls_calloc calloc |
#define mbedtls_snprintf snprintf |
#endif |
#if defined(MBEDTLS_THREADING_C) |
#include "mbedtls/threading.h" |
#endif |
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) |
#include <windows.h> |
#else |
#include <time.h> |
#endif |
#if defined(MBEDTLS_FS_IO) |
#include <stdio.h> |
#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <dirent.h> |
#endif /* !_WIN32 || EFIX64 || EFI32 */ |
#endif |
/* |
* Item in a verification chain: cert and flags for it |
*/ |
typedef struct { |
mbedtls_x509_crt *crt; |
uint32_t flags; |
} x509_crt_verify_chain_item; |
/* |
* Max size of verification chain: end-entity + intermediates + trusted root |
*/ |
#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) |
/* |
* Default profile |
*/ |
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = |
{ |
#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) |
/* Allow SHA-1 (weak, but still safe in controlled environments) */ |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | |
#endif |
/* Only SHA-2 hashes */ |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), |
0xFFFFFFF, /* Any PK alg */ |
0xFFFFFFF, /* Any curve */ |
2048, |
}; |
/* |
* Next-default profile |
*/ |
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = |
{ |
/* Hashes from SHA-256 and above */ |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), |
0xFFFFFFF, /* Any PK alg */ |
#if defined(MBEDTLS_ECP_C) |
/* Curves at or above 128-bit security level */ |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), |
#else |
0, |
#endif |
2048, |
}; |
/* |
* NSA Suite B Profile |
*/ |
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = |
{ |
/* Only SHA-256 and 384 */ |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), |
/* Only ECDSA */ |
MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), |
#if defined(MBEDTLS_ECP_C) |
/* Only NIST P-256 and P-384 */ |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | |
MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), |
#else |
0, |
#endif |
0, |
}; |
/* |
* Check md_alg against profile |
* Return 0 if md_alg is acceptable for this profile, -1 otherwise |
*/ |
static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, |
mbedtls_md_type_t md_alg ) |
{ |
if( md_alg == MBEDTLS_MD_NONE ) |
return( -1 ); |
if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) |
return( 0 ); |
return( -1 ); |
} |
/* |
* Check pk_alg against profile |
* Return 0 if pk_alg is acceptable for this profile, -1 otherwise |
*/ |
static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, |
mbedtls_pk_type_t pk_alg ) |
{ |
if( pk_alg == MBEDTLS_PK_NONE ) |
return( -1 ); |
if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) |
return( 0 ); |
return( -1 ); |
} |
/* |
* Check key against profile |
* Return 0 if pk is acceptable for this profile, -1 otherwise |
*/ |
static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, |
const mbedtls_pk_context *pk ) |
{ |
const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); |
#if defined(MBEDTLS_RSA_C) |
if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) |
{ |
if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) |
return( 0 ); |
return( -1 ); |
} |
#endif |
#if defined(MBEDTLS_ECP_C) |
if( pk_alg == MBEDTLS_PK_ECDSA || |
pk_alg == MBEDTLS_PK_ECKEY || |
pk_alg == MBEDTLS_PK_ECKEY_DH ) |
{ |
const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; |
if( gid == MBEDTLS_ECP_DP_NONE ) |
return( -1 ); |
if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) |
return( 0 ); |
return( -1 ); |
} |
#endif |
return( -1 ); |
} |
/* |
* Like memcmp, but case-insensitive and always returns -1 if different |
*/ |
static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) |
{ |
size_t i; |
unsigned char diff; |
const unsigned char *n1 = s1, *n2 = s2; |
for( i = 0; i < len; i++ ) |
{ |
diff = n1[i] ^ n2[i]; |
if( diff == 0 ) |
continue; |
if( diff == 32 && |
( ( n1[i] >= 'a' && n1[i] <= 'z' ) || |
( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) |
{ |
continue; |
} |
return( -1 ); |
} |
return( 0 ); |
} |
/* |
* Return 0 if name matches wildcard, -1 otherwise |
*/ |
static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) |
{ |
size_t i; |
size_t cn_idx = 0, cn_len = strlen( cn ); |
/* We can't have a match if there is no wildcard to match */ |
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) |
return( -1 ); |
for( i = 0; i < cn_len; ++i ) |
{ |
if( cn[i] == '.' ) |
{ |
cn_idx = i; |
break; |
} |
} |
if( cn_idx == 0 ) |
return( -1 ); |
if( cn_len - cn_idx == name->len - 1 && |
x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) |
{ |
return( 0 ); |
} |
return( -1 ); |
} |
/* |
* Compare two X.509 strings, case-insensitive, and allowing for some encoding |
* variations (but not all). |
* |
* Return 0 if equal, -1 otherwise. |
*/ |
static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) |
{ |
if( a->tag == b->tag && |
a->len == b->len && |
memcmp( a->p, b->p, b->len ) == 0 ) |
{ |
return( 0 ); |
} |
if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && |
( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && |
a->len == b->len && |
x509_memcasecmp( a->p, b->p, b->len ) == 0 ) |
{ |
return( 0 ); |
} |
return( -1 ); |
} |
/* |
* Compare two X.509 Names (aka rdnSequence). |
* |
* See RFC 5280 section 7.1, though we don't implement the whole algorithm: |
* we sometimes return unequal when the full algorithm would return equal, |
* but never the other way. (In particular, we don't do Unicode normalisation |
* or space folding.) |
* |
* Return 0 if equal, -1 otherwise. |
*/ |
static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) |
{ |
/* Avoid recursion, it might not be optimised by the compiler */ |
while( a != NULL || b != NULL ) |
{ |
if( a == NULL || b == NULL ) |
return( -1 ); |
/* type */ |
if( a->oid.tag != b->oid.tag || |
a->oid.len != b->oid.len || |
memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) |
{ |
return( -1 ); |
} |
/* value */ |
if( x509_string_cmp( &a->val, &b->val ) != 0 ) |
return( -1 ); |
/* structure of the list of sets */ |
if( a->next_merged != b->next_merged ) |
return( -1 ); |
a = a->next; |
b = b->next; |
} |
/* a == NULL == b */ |
return( 0 ); |
} |
/* |
* Reset (init or clear) a verify_chain |
*/ |
static void x509_crt_verify_chain_reset( |
mbedtls_x509_crt_verify_chain *ver_chain ) |
{ |
size_t i; |
for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) |
{ |
ver_chain->items[i].crt = NULL; |
ver_chain->items[i].flags = (uint32_t) -1; |
} |
ver_chain->len = 0; |
} |
/* |
* Version ::= INTEGER { v1(0), v2(1), v3(2) } |
*/ |
static int x509_get_version( unsigned char **p, |
const unsigned char *end, |
int *ver ) |
{ |
int ret; |
size_t len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
{ |
*ver = 0; |
return( 0 ); |
} |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
end = *p + len; |
if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); |
if( *p != end ) |
return( MBEDTLS_ERR_X509_INVALID_VERSION + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* Validity ::= SEQUENCE { |
* notBefore Time, |
* notAfter Time } |
*/ |
static int x509_get_dates( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_time *from, |
mbedtls_x509_time *to ) |
{ |
int ret; |
size_t len; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); |
end = *p + len; |
if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) |
return( ret ); |
if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) |
return( ret ); |
if( *p != end ) |
return( MBEDTLS_ERR_X509_INVALID_DATE + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* X.509 v2/v3 unique identifier (not parsed) |
*/ |
static int x509_get_uid( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_buf *uid, int n ) |
{ |
int ret; |
if( *p == end ) |
return( 0 ); |
uid->tag = **p; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, |
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
return( 0 ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
uid->p = *p; |
*p += uid->len; |
return( 0 ); |
} |
static int x509_get_basic_constraints( unsigned char **p, |
const unsigned char *end, |
int *ca_istrue, |
int *max_pathlen ) |
{ |
int ret; |
size_t len; |
/* |
* BasicConstraints ::= SEQUENCE { |
* cA BOOLEAN DEFAULT FALSE, |
* pathLenConstraint INTEGER (0..MAX) OPTIONAL } |
*/ |
*ca_istrue = 0; /* DEFAULT FALSE */ |
*max_pathlen = 0; /* endless */ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( *p == end ) |
return( 0 ); |
if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
ret = mbedtls_asn1_get_int( p, end, ca_istrue ); |
if( ret != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( *ca_istrue != 0 ) |
*ca_istrue = 1; |
} |
if( *p == end ) |
return( 0 ); |
if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( *p != end ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
(*max_pathlen)++; |
return( 0 ); |
} |
static int x509_get_ns_cert_type( unsigned char **p, |
const unsigned char *end, |
unsigned char *ns_cert_type) |
{ |
int ret; |
mbedtls_x509_bitstring bs = { 0, 0, NULL }; |
if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( bs.len != 1 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
/* Get actual bitstring */ |
*ns_cert_type = *bs.p; |
return( 0 ); |
} |
static int x509_get_key_usage( unsigned char **p, |
const unsigned char *end, |
unsigned int *key_usage) |
{ |
int ret; |
size_t i; |
mbedtls_x509_bitstring bs = { 0, 0, NULL }; |
if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( bs.len < 1 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
/* Get actual bitstring */ |
*key_usage = 0; |
for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) |
{ |
*key_usage |= (unsigned int) bs.p[i] << (8*i); |
} |
return( 0 ); |
} |
/* |
* ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId |
* |
* KeyPurposeId ::= OBJECT IDENTIFIER |
*/ |
static int x509_get_ext_key_usage( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_sequence *ext_key_usage) |
{ |
int ret; |
if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
/* Sequence length must be >= 1 */ |
if( ext_key_usage->buf.p == NULL ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_INVALID_LENGTH ); |
return( 0 ); |
} |
/* |
* SubjectAltName ::= GeneralNames |
* |
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName |
* |
* GeneralName ::= CHOICE { |
* otherName [0] OtherName, |
* rfc822Name [1] IA5String, |
* dNSName [2] IA5String, |
* x400Address [3] ORAddress, |
* directoryName [4] Name, |
* ediPartyName [5] EDIPartyName, |
* uniformResourceIdentifier [6] IA5String, |
* iPAddress [7] OCTET STRING, |
* registeredID [8] OBJECT IDENTIFIER } |
* |
* OtherName ::= SEQUENCE { |
* type-id OBJECT IDENTIFIER, |
* value [0] EXPLICIT ANY DEFINED BY type-id } |
* |
* EDIPartyName ::= SEQUENCE { |
* nameAssigner [0] DirectoryString OPTIONAL, |
* partyName [1] DirectoryString } |
* |
* NOTE: we only parse and use dNSName at this point. |
*/ |
static int x509_get_subject_alt_name( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_sequence *subject_alt_name ) |
{ |
int ret; |
size_t len, tag_len; |
mbedtls_asn1_buf *buf; |
unsigned char tag; |
mbedtls_asn1_sequence *cur = subject_alt_name; |
/* Get main sequence tag */ |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( *p + len != end ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
while( *p < end ) |
{ |
if( ( end - *p ) < 1 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
tag = **p; |
(*p)++; |
if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != |
MBEDTLS_ASN1_CONTEXT_SPECIFIC ) |
{ |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
} |
/* Skip everything but DNS name */ |
if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) |
{ |
*p += tag_len; |
continue; |
} |
/* Allocate and assign next pointer */ |
if( cur->buf.p != NULL ) |
{ |
if( cur->next != NULL ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); |
cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); |
if( cur->next == NULL ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_ALLOC_FAILED ); |
cur = cur->next; |
} |
buf = &(cur->buf); |
buf->tag = tag; |
buf->p = *p; |
buf->len = tag_len; |
*p += buf->len; |
} |
/* Set final sequence entry's next pointer to NULL */ |
cur->next = NULL; |
if( *p != end ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* X.509 v3 extensions |
* |
*/ |
static int x509_get_crt_ext( unsigned char **p, |
const unsigned char *end, |
mbedtls_x509_crt *crt ) |
{ |
int ret; |
size_t len; |
unsigned char *end_ext_data, *end_ext_octet; |
if( *p == end ) |
return( 0 ); |
if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) |
return( ret ); |
end = crt->v3_ext.p + crt->v3_ext.len; |
while( *p < end ) |
{ |
/* |
* Extension ::= SEQUENCE { |
* extnID OBJECT IDENTIFIER, |
* critical BOOLEAN DEFAULT FALSE, |
* extnValue OCTET STRING } |
*/ |
mbedtls_x509_buf extn_oid = {0, 0, NULL}; |
int is_critical = 0; /* DEFAULT FALSE */ |
int ext_type = 0; |
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
end_ext_data = *p + len; |
/* Get extension ID */ |
if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, |
MBEDTLS_ASN1_OID ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
extn_oid.tag = MBEDTLS_ASN1_OID; |
extn_oid.p = *p; |
*p += extn_oid.len; |
/* Get optional critical */ |
if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && |
( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
/* Data should be octet string type */ |
if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, |
MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); |
end_ext_octet = *p + len; |
if( end_ext_octet != end_ext_data ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
/* |
* Detect supported extensions |
*/ |
ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); |
if( ret != 0 ) |
{ |
/* No parser found, skip extension */ |
*p = end_ext_octet; |
#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) |
if( is_critical ) |
{ |
/* Data is marked as critical: fail */ |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); |
} |
#endif |
continue; |
} |
/* Forbid repeated extensions */ |
if( ( crt->ext_types & ext_type ) != 0 ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); |
crt->ext_types |= ext_type; |
switch( ext_type ) |
{ |
case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: |
/* Parse basic constraints */ |
if( ( ret = x509_get_basic_constraints( p, end_ext_octet, |
&crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) |
return( ret ); |
break; |
case MBEDTLS_X509_EXT_KEY_USAGE: |
/* Parse key usage */ |
if( ( ret = x509_get_key_usage( p, end_ext_octet, |
&crt->key_usage ) ) != 0 ) |
return( ret ); |
break; |
case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: |
/* Parse extended key usage */ |
if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, |
&crt->ext_key_usage ) ) != 0 ) |
return( ret ); |
break; |
case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: |
/* Parse subject alt name */ |
if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, |
&crt->subject_alt_names ) ) != 0 ) |
return( ret ); |
break; |
case MBEDTLS_X509_EXT_NS_CERT_TYPE: |
/* Parse netscape certificate type */ |
if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, |
&crt->ns_cert_type ) ) != 0 ) |
return( ret ); |
break; |
default: |
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); |
} |
} |
if( *p != end ) |
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
return( 0 ); |
} |
/* |
* Parse and fill a single X.509 certificate in DER format |
*/ |
static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, |
size_t buflen ) |
{ |
int ret; |
size_t len; |
unsigned char *p, *end, *crt_end; |
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; |
memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); |
memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); |
memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); |
/* |
* Check for valid input |
*/ |
if( crt == NULL || buf == NULL ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
// Use the original buffer until we figure out actual length |
p = (unsigned char*) buf; |
len = buflen; |
end = p + len; |
/* |
* Certificate ::= SEQUENCE { |
* tbsCertificate TBSCertificate, |
* signatureAlgorithm AlgorithmIdentifier, |
* signatureValue BIT STRING } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT ); |
} |
if( len > (size_t) ( end - p ) ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
crt_end = p + len; |
// Create and populate a new buffer for the raw field |
crt->raw.len = crt_end - buf; |
crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); |
if( p == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
memcpy( p, buf, crt->raw.len ); |
// Direct pointers to the new buffer |
p += crt->raw.len - len; |
end = crt_end = p + len; |
/* |
* TBSCertificate ::= SEQUENCE { |
*/ |
crt->tbs.p = p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
end = p + len; |
crt->tbs.len = end - crt->tbs.p; |
/* |
* Version ::= INTEGER { v1(0), v2(1), v3(2) } |
* |
* CertificateSerialNumber ::= INTEGER |
* |
* signature AlgorithmIdentifier |
*/ |
if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || |
( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || |
( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, |
&sig_params1 ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
if( crt->version < 0 || crt->version > 2 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); |
} |
crt->version++; |
if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, |
&crt->sig_md, &crt->sig_pk, |
&crt->sig_opts ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
/* |
* issuer Name |
*/ |
crt->issuer_raw.p = p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
crt->issuer_raw.len = p - crt->issuer_raw.p; |
/* |
* Validity ::= SEQUENCE { |
* notBefore Time, |
* notAfter Time } |
* |
*/ |
if( ( ret = x509_get_dates( &p, end, &crt->valid_from, |
&crt->valid_to ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
/* |
* subject Name |
*/ |
crt->subject_raw.p = p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
crt->subject_raw.len = p - crt->subject_raw.p; |
/* |
* SubjectPublicKeyInfo |
*/ |
if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
/* |
* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, |
* -- If present, version shall be v2 or v3 |
* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, |
* -- If present, version shall be v2 or v3 |
* extensions [3] EXPLICIT Extensions OPTIONAL |
* -- If present, version shall be v3 |
*/ |
if( crt->version == 2 || crt->version == 3 ) |
{ |
ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); |
if( ret != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
} |
if( crt->version == 2 || crt->version == 3 ) |
{ |
ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); |
if( ret != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
} |
#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) |
if( crt->version == 3 ) |
#endif |
{ |
ret = x509_get_crt_ext( &p, end, crt ); |
if( ret != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
} |
if( p != end ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
end = crt_end; |
/* |
* } |
* -- end of TBSCertificate |
* |
* signatureAlgorithm AlgorithmIdentifier, |
* signatureValue BIT STRING |
*/ |
if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
if( crt->sig_oid.len != sig_oid2.len || |
memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || |
sig_params1.len != sig_params2.len || |
( sig_params1.len != 0 && |
memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_SIG_MISMATCH ); |
} |
if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( ret ); |
} |
if( p != end ) |
{ |
mbedtls_x509_crt_free( crt ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
return( 0 ); |
} |
/* |
* Parse one X.509 certificate in DER format from a buffer and add them to a |
* chained list |
*/ |
int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, |
size_t buflen ) |
{ |
int ret; |
mbedtls_x509_crt *crt = chain, *prev = NULL; |
/* |
* Check for valid input |
*/ |
if( crt == NULL || buf == NULL ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
while( crt->version != 0 && crt->next != NULL ) |
{ |
prev = crt; |
crt = crt->next; |
} |
/* |
* Add new certificate on the end of the chain if needed. |
*/ |
if( crt->version != 0 && crt->next == NULL ) |
{ |
crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); |
if( crt->next == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
prev = crt; |
mbedtls_x509_crt_init( crt->next ); |
crt = crt->next; |
} |
if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) |
{ |
if( prev ) |
prev->next = NULL; |
if( crt != chain ) |
mbedtls_free( crt ); |
return( ret ); |
} |
return( 0 ); |
} |
/* |
* Parse one or more PEM certificates from a buffer and add them to the chained |
* list |
*/ |
int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) |
{ |
#if defined(MBEDTLS_PEM_PARSE_C) |
int success = 0, first_error = 0, total_failed = 0; |
int buf_format = MBEDTLS_X509_FORMAT_DER; |
#endif |
/* |
* Check for valid input |
*/ |
if( chain == NULL || buf == NULL ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
/* |
* Determine buffer content. Buffer contains either one DER certificate or |
* one or more PEM certificates. |
*/ |
#if defined(MBEDTLS_PEM_PARSE_C) |
if( buflen != 0 && buf[buflen - 1] == '\0' && |
strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) |
{ |
buf_format = MBEDTLS_X509_FORMAT_PEM; |
} |
if( buf_format == MBEDTLS_X509_FORMAT_DER ) |
return mbedtls_x509_crt_parse_der( chain, buf, buflen ); |
#else |
return mbedtls_x509_crt_parse_der( chain, buf, buflen ); |
#endif |
#if defined(MBEDTLS_PEM_PARSE_C) |
if( buf_format == MBEDTLS_X509_FORMAT_PEM ) |
{ |
int ret; |
mbedtls_pem_context pem; |
/* 1 rather than 0 since the terminating NULL byte is counted in */ |
while( buflen > 1 ) |
{ |
size_t use_len; |
mbedtls_pem_init( &pem ); |
/* If we get there, we know the string is null-terminated */ |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN CERTIFICATE-----", |
"-----END CERTIFICATE-----", |
buf, NULL, 0, &use_len ); |
if( ret == 0 ) |
{ |
/* |
* Was PEM encoded |
*/ |
buflen -= use_len; |
buf += use_len; |
} |
else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) |
{ |
return( ret ); |
} |
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
{ |
mbedtls_pem_free( &pem ); |
/* |
* PEM header and footer were found |
*/ |
buflen -= use_len; |
buf += use_len; |
if( first_error == 0 ) |
first_error = ret; |
total_failed++; |
continue; |
} |
else |
break; |
ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); |
mbedtls_pem_free( &pem ); |
if( ret != 0 ) |
{ |
/* |
* Quit parsing on a memory error |
*/ |
if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) |
return( ret ); |
if( first_error == 0 ) |
first_error = ret; |
total_failed++; |
continue; |
} |
success = 1; |
} |
} |
if( success ) |
return( total_failed ); |
else if( first_error ) |
return( first_error ); |
else |
return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); |
#endif /* MBEDTLS_PEM_PARSE_C */ |
} |
#if defined(MBEDTLS_FS_IO) |
/* |
* Load one or more certificates and add them to the chained list |
*/ |
int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) |
{ |
int ret; |
size_t n; |
unsigned char *buf; |
if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) |
return( ret ); |
ret = mbedtls_x509_crt_parse( chain, buf, n ); |
mbedtls_platform_zeroize( buf, n ); |
mbedtls_free( buf ); |
return( ret ); |
} |
int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) |
{ |
int ret = 0; |
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) |
int w_ret; |
WCHAR szDir[MAX_PATH]; |
char filename[MAX_PATH]; |
char *p; |
size_t len = strlen( path ); |
WIN32_FIND_DATAW file_data; |
HANDLE hFind; |
if( len > MAX_PATH - 3 ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
memset( szDir, 0, sizeof(szDir) ); |
memset( filename, 0, MAX_PATH ); |
memcpy( filename, path, len ); |
filename[len++] = '\\'; |
p = filename + len; |
filename[len++] = '*'; |
w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, |
MAX_PATH - 3 ); |
if( w_ret == 0 ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
hFind = FindFirstFileW( szDir, &file_data ); |
if( hFind == INVALID_HANDLE_VALUE ) |
return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); |
len = MAX_PATH - len; |
do |
{ |
memset( p, 0, len ); |
if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) |
continue; |
w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, |
lstrlenW( file_data.cFileName ), |
p, (int) len - 1, |
NULL, NULL ); |
if( w_ret == 0 ) |
{ |
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; |
goto cleanup; |
} |
w_ret = mbedtls_x509_crt_parse_file( chain, filename ); |
if( w_ret < 0 ) |
ret++; |
else |
ret += w_ret; |
} |
while( FindNextFileW( hFind, &file_data ) != 0 ); |
if( GetLastError() != ERROR_NO_MORE_FILES ) |
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; |
cleanup: |
FindClose( hFind ); |
#else /* _WIN32 */ |
int t_ret; |
int snp_ret; |
struct stat sb; |
struct dirent *entry; |
char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; |
DIR *dir = opendir( path ); |
if( dir == NULL ) |
return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); |
#if defined(MBEDTLS_THREADING_C) |
if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) |
{ |
closedir( dir ); |
return( ret ); |
} |
#endif /* MBEDTLS_THREADING_C */ |
while( ( entry = readdir( dir ) ) != NULL ) |
{ |
snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, |
"%s/%s", path, entry->d_name ); |
if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) |
{ |
ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; |
goto cleanup; |
} |
else if( stat( entry_name, &sb ) == -1 ) |
{ |
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; |
goto cleanup; |
} |
if( !S_ISREG( sb.st_mode ) ) |
continue; |
// Ignore parse errors |
// |
t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); |
if( t_ret < 0 ) |
ret++; |
else |
ret += t_ret; |
} |
cleanup: |
closedir( dir ); |
#if defined(MBEDTLS_THREADING_C) |
if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) |
ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; |
#endif /* MBEDTLS_THREADING_C */ |
#endif /* _WIN32 */ |
return( ret ); |
} |
#endif /* MBEDTLS_FS_IO */ |
static int x509_info_subject_alt_name( char **buf, size_t *size, |
const mbedtls_x509_sequence *subject_alt_name ) |
{ |
size_t i; |
size_t n = *size; |
char *p = *buf; |
const mbedtls_x509_sequence *cur = subject_alt_name; |
const char *sep = ""; |
size_t sep_len = 0; |
while( cur != NULL ) |
{ |
if( cur->buf.len + sep_len >= n ) |
{ |
*p = '\0'; |
return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); |
} |
n -= cur->buf.len + sep_len; |
for( i = 0; i < sep_len; i++ ) |
*p++ = sep[i]; |
for( i = 0; i < cur->buf.len; i++ ) |
*p++ = cur->buf.p[i]; |
sep = ", "; |
sep_len = 2; |
cur = cur->next; |
} |
*p = '\0'; |
*size = n; |
*buf = p; |
return( 0 ); |
} |
#define PRINT_ITEM(i) \ |
{ \ |
ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ |
MBEDTLS_X509_SAFE_SNPRINTF; \ |
sep = ", "; \ |
} |
#define CERT_TYPE(type,name) \ |
if( ns_cert_type & (type) ) \ |
PRINT_ITEM( name ); |
static int x509_info_cert_type( char **buf, size_t *size, |
unsigned char ns_cert_type ) |
{ |
int ret; |
size_t n = *size; |
char *p = *buf; |
const char *sep = ""; |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); |
CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); |
*size = n; |
*buf = p; |
return( 0 ); |
} |
#define KEY_USAGE(code,name) \ |
if( key_usage & (code) ) \ |
PRINT_ITEM( name ); |
static int x509_info_key_usage( char **buf, size_t *size, |
unsigned int key_usage ) |
{ |
int ret; |
size_t n = *size; |
char *p = *buf; |
const char *sep = ""; |
KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); |
KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); |
KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); |
KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); |
KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); |
KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); |
KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); |
KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); |
KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); |
*size = n; |
*buf = p; |
return( 0 ); |
} |
static int x509_info_ext_key_usage( char **buf, size_t *size, |
const mbedtls_x509_sequence *extended_key_usage ) |
{ |
int ret; |
const char *desc; |
size_t n = *size; |
char *p = *buf; |
const mbedtls_x509_sequence *cur = extended_key_usage; |
const char *sep = ""; |
while( cur != NULL ) |
{ |
if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) |
desc = "???"; |
ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
sep = ", "; |
cur = cur->next; |
} |
*size = n; |
*buf = p; |
return( 0 ); |
} |
/* |
* Return an informational string about the certificate. |
*/ |
#define BEFORE_COLON 18 |
#define BC "18" |
int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, |
const mbedtls_x509_crt *crt ) |
{ |
int ret; |
size_t n; |
char *p; |
char key_size_str[BEFORE_COLON]; |
p = buf; |
n = size; |
if( NULL == crt ) |
{ |
ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
return( (int) ( size - n ) ); |
} |
ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", |
prefix, crt->version ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "%sserial number : ", |
prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ |
"%04d-%02d-%02d %02d:%02d:%02d", prefix, |
crt->valid_from.year, crt->valid_from.mon, |
crt->valid_from.day, crt->valid_from.hour, |
crt->valid_from.min, crt->valid_from.sec ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ |
"%04d-%02d-%02d %02d:%02d:%02d", prefix, |
crt->valid_to.year, crt->valid_to.mon, |
crt->valid_to.day, crt->valid_to.hour, |
crt->valid_to.min, crt->valid_to.sec ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, |
crt->sig_md, crt->sig_opts ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
/* Key size */ |
if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, |
mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) |
{ |
return( ret ); |
} |
ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, |
(int) mbedtls_pk_get_bitlen( &crt->pk ) ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
/* |
* Optional extensions |
*/ |
if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) |
{ |
ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, |
crt->ca_istrue ? "true" : "false" ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
if( crt->max_pathlen > 0 ) |
{ |
ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
} |
} |
if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) |
{ |
ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
if( ( ret = x509_info_subject_alt_name( &p, &n, |
&crt->subject_alt_names ) ) != 0 ) |
return( ret ); |
} |
if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) |
{ |
ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) |
return( ret ); |
} |
if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) |
{ |
ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) |
return( ret ); |
} |
if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) |
{ |
ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
if( ( ret = x509_info_ext_key_usage( &p, &n, |
&crt->ext_key_usage ) ) != 0 ) |
return( ret ); |
} |
ret = mbedtls_snprintf( p, n, "\n" ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
return( (int) ( size - n ) ); |
} |
struct x509_crt_verify_string { |
int code; |
const char *string; |
}; |
static const struct x509_crt_verify_string x509_crt_verify_strings[] = { |
{ MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, |
{ MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, |
{ MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, |
{ MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, |
{ MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, |
{ MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, |
{ MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, |
{ MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, |
{ MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, |
{ MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, |
{ MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, |
{ MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, |
{ MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, |
{ MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, |
{ MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, |
{ MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, |
{ MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, |
{ MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, |
{ MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, |
{ MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, |
{ 0, NULL } |
}; |
int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, |
uint32_t flags ) |
{ |
int ret; |
const struct x509_crt_verify_string *cur; |
char *p = buf; |
size_t n = size; |
for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) |
{ |
if( ( flags & cur->code ) == 0 ) |
continue; |
ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
flags ^= cur->code; |
} |
if( flags != 0 ) |
{ |
ret = mbedtls_snprintf( p, n, "%sUnknown reason " |
"(this should not happen)\n", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
} |
return( (int) ( size - n ) ); |
} |
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) |
int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, |
unsigned int usage ) |
{ |
unsigned int usage_must, usage_may; |
unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY |
| MBEDTLS_X509_KU_DECIPHER_ONLY; |
if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) |
return( 0 ); |
usage_must = usage & ~may_mask; |
if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
usage_may = usage & may_mask; |
if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
return( 0 ); |
} |
#endif |
#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) |
int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, |
const char *usage_oid, |
size_t usage_len ) |
{ |
const mbedtls_x509_sequence *cur; |
/* Extension is not mandatory, absent means no restriction */ |
if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) |
return( 0 ); |
/* |
* Look for the requested usage (or wildcard ANY) in our list |
*/ |
for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) |
{ |
const mbedtls_x509_buf *cur_oid = &cur->buf; |
if( cur_oid->len == usage_len && |
memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) |
{ |
return( 0 ); |
} |
if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) |
return( 0 ); |
} |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
} |
#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ |
#if defined(MBEDTLS_X509_CRL_PARSE_C) |
/* |
* Return 1 if the certificate is revoked, or 0 otherwise. |
*/ |
int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) |
{ |
const mbedtls_x509_crl_entry *cur = &crl->entry; |
while( cur != NULL && cur->serial.len != 0 ) |
{ |
if( crt->serial.len == cur->serial.len && |
memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) |
{ |
if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) |
return( 1 ); |
} |
cur = cur->next; |
} |
return( 0 ); |
} |
/* |
* Check that the given certificate is not revoked according to the CRL. |
* Skip validation if no CRL for the given CA is present. |
*/ |
static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, |
mbedtls_x509_crl *crl_list, |
const mbedtls_x509_crt_profile *profile ) |
{ |
int flags = 0; |
unsigned char hash[MBEDTLS_MD_MAX_SIZE]; |
const mbedtls_md_info_t *md_info; |
if( ca == NULL ) |
return( flags ); |
while( crl_list != NULL ) |
{ |
if( crl_list->version == 0 || |
x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) |
{ |
crl_list = crl_list->next; |
continue; |
} |
/* |
* Check if the CA is configured to sign CRLs |
*/ |
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) |
if( mbedtls_x509_crt_check_key_usage( ca, |
MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) |
{ |
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; |
break; |
} |
#endif |
/* |
* Check if CRL is correctly signed by the trusted CA |
*/ |
if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) |
flags |= MBEDTLS_X509_BADCRL_BAD_MD; |
if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) |
flags |= MBEDTLS_X509_BADCRL_BAD_PK; |
md_info = mbedtls_md_info_from_type( crl_list->sig_md ); |
if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) |
{ |
/* Note: this can't happen except after an internal error */ |
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; |
break; |
} |
if( x509_profile_check_key( profile, &ca->pk ) != 0 ) |
flags |= MBEDTLS_X509_BADCERT_BAD_KEY; |
if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, |
crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), |
crl_list->sig.p, crl_list->sig.len ) != 0 ) |
{ |
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; |
break; |
} |
/* |
* Check for validity of CRL (Do not drop out) |
*/ |
if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) |
flags |= MBEDTLS_X509_BADCRL_EXPIRED; |
if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) |
flags |= MBEDTLS_X509_BADCRL_FUTURE; |
/* |
* Check if certificate is revoked |
*/ |
if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) |
{ |
flags |= MBEDTLS_X509_BADCERT_REVOKED; |
break; |
} |
crl_list = crl_list->next; |
} |
return( flags ); |
} |
#endif /* MBEDTLS_X509_CRL_PARSE_C */ |
/* |
* Check the signature of a certificate by its parent |
*/ |
static int x509_crt_check_signature( const mbedtls_x509_crt *child, |
mbedtls_x509_crt *parent, |
mbedtls_x509_crt_restart_ctx *rs_ctx ) |
{ |
const mbedtls_md_info_t *md_info; |
unsigned char hash[MBEDTLS_MD_MAX_SIZE]; |
md_info = mbedtls_md_info_from_type( child->sig_md ); |
if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) |
{ |
/* Note: this can't happen except after an internal error */ |
return( -1 ); |
} |
/* Skip expensive computation on obvious mismatch */ |
if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) |
return( -1 ); |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) |
{ |
return( mbedtls_pk_verify_restartable( &parent->pk, |
child->sig_md, hash, mbedtls_md_get_size( md_info ), |
child->sig.p, child->sig.len, &rs_ctx->pk ) ); |
} |
#else |
(void) rs_ctx; |
#endif |
return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, |
child->sig_md, hash, mbedtls_md_get_size( md_info ), |
child->sig.p, child->sig.len ) ); |
} |
/* |
* Check if 'parent' is a suitable parent (signing CA) for 'child'. |
* Return 0 if yes, -1 if not. |
* |
* top means parent is a locally-trusted certificate |
*/ |
static int x509_crt_check_parent( const mbedtls_x509_crt *child, |
const mbedtls_x509_crt *parent, |
int top ) |
{ |
int need_ca_bit; |
/* Parent must be the issuer */ |
if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) |
return( -1 ); |
/* Parent must have the basicConstraints CA bit set as a general rule */ |
need_ca_bit = 1; |
/* Exception: v1/v2 certificates that are locally trusted. */ |
if( top && parent->version < 3 ) |
need_ca_bit = 0; |
if( need_ca_bit && ! parent->ca_istrue ) |
return( -1 ); |
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) |
if( need_ca_bit && |
mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) |
{ |
return( -1 ); |
} |
#endif |
return( 0 ); |
} |
/* |
* Find a suitable parent for child in candidates, or return NULL. |
* |
* Here suitable is defined as: |
* 1. subject name matches child's issuer |
* 2. if necessary, the CA bit is set and key usage allows signing certs |
* 3. for trusted roots, the signature is correct |
* (for intermediates, the signature is checked and the result reported) |
* 4. pathlen constraints are satisfied |
* |
* If there's a suitable candidate which is also time-valid, return the first |
* such. Otherwise, return the first suitable candidate (or NULL if there is |
* none). |
* |
* The rationale for this rule is that someone could have a list of trusted |
* roots with two versions on the same root with different validity periods. |
* (At least one user reported having such a list and wanted it to just work.) |
* The reason we don't just require time-validity is that generally there is |
* only one version, and if it's expired we want the flags to state that |
* rather than NOT_TRUSTED, as would be the case if we required it here. |
* |
* The rationale for rule 3 (signature for trusted roots) is that users might |
* have two versions of the same CA with different keys in their list, and the |
* way we select the correct one is by checking the signature (as we don't |
* rely on key identifier extensions). (This is one way users might choose to |
* handle key rollover, another relies on self-issued certs, see [SIRO].) |
* |
* Arguments: |
* - [in] child: certificate for which we're looking for a parent |
* - [in] candidates: chained list of potential parents |
* - [out] r_parent: parent found (or NULL) |
* - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 |
* - [in] top: 1 if candidates consists of trusted roots, ie we're at the top |
* of the chain, 0 otherwise |
* - [in] path_cnt: number of intermediates seen so far |
* - [in] self_cnt: number of self-signed intermediates seen so far |
* (will never be greater than path_cnt) |
* - [in-out] rs_ctx: context for restarting operations |
* |
* Return value: |
* - 0 on success |
* - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise |
*/ |
static int x509_crt_find_parent_in( |
mbedtls_x509_crt *child, |
mbedtls_x509_crt *candidates, |
mbedtls_x509_crt **r_parent, |
int *r_signature_is_good, |
int top, |
unsigned path_cnt, |
unsigned self_cnt, |
mbedtls_x509_crt_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_x509_crt *parent, *fallback_parent; |
int signature_is_good, fallback_signature_is_good; |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* did we have something in progress? */ |
if( rs_ctx != NULL && rs_ctx->parent != NULL ) |
{ |
/* restore saved state */ |
parent = rs_ctx->parent; |
fallback_parent = rs_ctx->fallback_parent; |
fallback_signature_is_good = rs_ctx->fallback_signature_is_good; |
/* clear saved state */ |
rs_ctx->parent = NULL; |
rs_ctx->fallback_parent = NULL; |
rs_ctx->fallback_signature_is_good = 0; |
/* resume where we left */ |
goto check_signature; |
} |
#endif |
fallback_parent = NULL; |
fallback_signature_is_good = 0; |
for( parent = candidates; parent != NULL; parent = parent->next ) |
{ |
/* basic parenting skills (name, CA bit, key usage) */ |
if( x509_crt_check_parent( child, parent, top ) != 0 ) |
continue; |
/* +1 because stored max_pathlen is 1 higher that the actual value */ |
if( parent->max_pathlen > 0 && |
(size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) |
{ |
continue; |
} |
/* Signature */ |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
check_signature: |
#endif |
ret = x509_crt_check_signature( child, parent, rs_ctx ); |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
{ |
/* save state */ |
rs_ctx->parent = parent; |
rs_ctx->fallback_parent = fallback_parent; |
rs_ctx->fallback_signature_is_good = fallback_signature_is_good; |
return( ret ); |
} |
#else |
(void) ret; |
#endif |
signature_is_good = ret == 0; |
if( top && ! signature_is_good ) |
continue; |
/* optional time check */ |
if( mbedtls_x509_time_is_past( &parent->valid_to ) || |
mbedtls_x509_time_is_future( &parent->valid_from ) ) |
{ |
if( fallback_parent == NULL ) |
{ |
fallback_parent = parent; |
fallback_signature_is_good = signature_is_good; |
} |
continue; |
} |
*r_parent = parent; |
*r_signature_is_good = signature_is_good; |
break; |
} |
if( parent == NULL ) |
{ |
*r_parent = fallback_parent; |
*r_signature_is_good = fallback_signature_is_good; |
} |
return( 0 ); |
} |
/* |
* Find a parent in trusted CAs or the provided chain, or return NULL. |
* |
* Searches in trusted CAs first, and return the first suitable parent found |
* (see find_parent_in() for definition of suitable). |
* |
* Arguments: |
* - [in] child: certificate for which we're looking for a parent, followed |
* by a chain of possible intermediates |
* - [in] trust_ca: list of locally trusted certificates |
* - [out] parent: parent found (or NULL) |
* - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 |
* - [out] signature_is_good: 1 if child signature by parent is valid, or 0 |
* - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) |
* - [in] self_cnt: number of self-signed certs in the chain so far |
* (will always be no greater than path_cnt) |
* - [in-out] rs_ctx: context for restarting operations |
* |
* Return value: |
* - 0 on success |
* - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise |
*/ |
static int x509_crt_find_parent( |
mbedtls_x509_crt *child, |
mbedtls_x509_crt *trust_ca, |
mbedtls_x509_crt **parent, |
int *parent_is_trusted, |
int *signature_is_good, |
unsigned path_cnt, |
unsigned self_cnt, |
mbedtls_x509_crt_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_x509_crt *search_list; |
*parent_is_trusted = 1; |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* restore then clear saved state if we have some stored */ |
if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) |
{ |
*parent_is_trusted = rs_ctx->parent_is_trusted; |
rs_ctx->parent_is_trusted = -1; |
} |
#endif |
while( 1 ) { |
search_list = *parent_is_trusted ? trust_ca : child->next; |
ret = x509_crt_find_parent_in( child, search_list, |
parent, signature_is_good, |
*parent_is_trusted, |
path_cnt, self_cnt, rs_ctx ); |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
{ |
/* save state */ |
rs_ctx->parent_is_trusted = *parent_is_trusted; |
return( ret ); |
} |
#else |
(void) ret; |
#endif |
/* stop here if found or already in second iteration */ |
if( *parent != NULL || *parent_is_trusted == 0 ) |
break; |
/* prepare second iteration */ |
*parent_is_trusted = 0; |
} |
/* extra precaution against mistakes in the caller */ |
if( *parent == NULL ) |
{ |
*parent_is_trusted = 0; |
*signature_is_good = 0; |
} |
return( 0 ); |
} |
/* |
* Check if an end-entity certificate is locally trusted |
* |
* Currently we require such certificates to be self-signed (actually only |
* check for self-issued as self-signatures are not checked) |
*/ |
static int x509_crt_check_ee_locally_trusted( |
mbedtls_x509_crt *crt, |
mbedtls_x509_crt *trust_ca ) |
{ |
mbedtls_x509_crt *cur; |
/* must be self-issued */ |
if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) |
return( -1 ); |
/* look for an exact match with trusted cert */ |
for( cur = trust_ca; cur != NULL; cur = cur->next ) |
{ |
if( crt->raw.len == cur->raw.len && |
memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) |
{ |
return( 0 ); |
} |
} |
/* too bad */ |
return( -1 ); |
} |
/* |
* Build and verify a certificate chain |
* |
* Given a peer-provided list of certificates EE, C1, ..., Cn and |
* a list of trusted certs R1, ... Rp, try to build and verify a chain |
* EE, Ci1, ... Ciq [, Rj] |
* such that every cert in the chain is a child of the next one, |
* jumping to a trusted root as early as possible. |
* |
* Verify that chain and return it with flags for all issues found. |
* |
* Special cases: |
* - EE == Rj -> return a one-element list containing it |
* - EE, Ci1, ..., Ciq cannot be continued with a trusted root |
* -> return that chain with NOT_TRUSTED set on Ciq |
* |
* Tests for (aspects of) this function should include at least: |
* - trusted EE |
* - EE -> trusted root |
* - EE -> intermediate CA -> trusted root |
* - if relevant: EE untrusted |
* - if relevant: EE -> intermediate, untrusted |
* with the aspect under test checked at each relevant level (EE, int, root). |
* For some aspects longer chains are required, but usually length 2 is |
* enough (but length 1 is not in general). |
* |
* Arguments: |
* - [in] crt: the cert list EE, C1, ..., Cn |
* - [in] trust_ca: the trusted list R1, ..., Rp |
* - [in] ca_crl, profile: as in verify_with_profile() |
* - [out] ver_chain: the built and verified chain |
* Only valid when return value is 0, may contain garbage otherwise! |
* Restart note: need not be the same when calling again to resume. |
* - [in-out] rs_ctx: context for restarting operations |
* |
* Return value: |
* - non-zero if the chain could not be fully built and examined |
* - 0 is the chain was successfully built and examined, |
* even if it was found to be invalid |
*/ |
static int x509_crt_verify_chain( |
mbedtls_x509_crt *crt, |
mbedtls_x509_crt *trust_ca, |
mbedtls_x509_crl *ca_crl, |
const mbedtls_x509_crt_profile *profile, |
mbedtls_x509_crt_verify_chain *ver_chain, |
mbedtls_x509_crt_restart_ctx *rs_ctx ) |
{ |
/* Don't initialize any of those variables here, so that the compiler can |
* catch potential issues with jumping ahead when restarting */ |
int ret; |
uint32_t *flags; |
mbedtls_x509_crt_verify_chain_item *cur; |
mbedtls_x509_crt *child; |
mbedtls_x509_crt *parent; |
int parent_is_trusted; |
int child_is_trusted; |
int signature_is_good; |
unsigned self_cnt; |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* resume if we had an operation in progress */ |
if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) |
{ |
/* restore saved state */ |
*ver_chain = rs_ctx->ver_chain; /* struct copy */ |
self_cnt = rs_ctx->self_cnt; |
/* restore derived state */ |
cur = &ver_chain->items[ver_chain->len - 1]; |
child = cur->crt; |
flags = &cur->flags; |
goto find_parent; |
} |
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
child = crt; |
self_cnt = 0; |
parent_is_trusted = 0; |
child_is_trusted = 0; |
while( 1 ) { |
/* Add certificate to the verification chain */ |
cur = &ver_chain->items[ver_chain->len]; |
cur->crt = child; |
cur->flags = 0; |
ver_chain->len++; |
flags = &cur->flags; |
/* Check time-validity (all certificates) */ |
if( mbedtls_x509_time_is_past( &child->valid_to ) ) |
*flags |= MBEDTLS_X509_BADCERT_EXPIRED; |
if( mbedtls_x509_time_is_future( &child->valid_from ) ) |
*flags |= MBEDTLS_X509_BADCERT_FUTURE; |
/* Stop here for trusted roots (but not for trusted EE certs) */ |
if( child_is_trusted ) |
return( 0 ); |
/* Check signature algorithm: MD & PK algs */ |
if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) |
*flags |= MBEDTLS_X509_BADCERT_BAD_MD; |
if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) |
*flags |= MBEDTLS_X509_BADCERT_BAD_PK; |
/* Special case: EE certs that are locally trusted */ |
if( ver_chain->len == 1 && |
x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) |
{ |
return( 0 ); |
} |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
find_parent: |
#endif |
/* Look for a parent in trusted CAs or up the chain */ |
ret = x509_crt_find_parent( child, trust_ca, &parent, |
&parent_is_trusted, &signature_is_good, |
ver_chain->len - 1, self_cnt, rs_ctx ); |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) |
{ |
/* save state */ |
rs_ctx->in_progress = x509_crt_rs_find_parent; |
rs_ctx->self_cnt = self_cnt; |
rs_ctx->ver_chain = *ver_chain; /* struct copy */ |
return( ret ); |
} |
#else |
(void) ret; |
#endif |
/* No parent? We're done here */ |
if( parent == NULL ) |
{ |
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; |
return( 0 ); |
} |
/* Count intermediate self-issued (not necessarily self-signed) certs. |
* These can occur with some strategies for key rollover, see [SIRO], |
* and should be excluded from max_pathlen checks. */ |
if( ver_chain->len != 1 && |
x509_name_cmp( &child->issuer, &child->subject ) == 0 ) |
{ |
self_cnt++; |
} |
/* path_cnt is 0 for the first intermediate CA, |
* and if parent is trusted it's not an intermediate CA */ |
if( ! parent_is_trusted && |
ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) |
{ |
/* return immediately to avoid overflow the chain array */ |
return( MBEDTLS_ERR_X509_FATAL_ERROR ); |
} |
/* signature was checked while searching parent */ |
if( ! signature_is_good ) |
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; |
/* check size of signing key */ |
if( x509_profile_check_key( profile, &parent->pk ) != 0 ) |
*flags |= MBEDTLS_X509_BADCERT_BAD_KEY; |
#if defined(MBEDTLS_X509_CRL_PARSE_C) |
/* Check trusted CA's CRL for the given crt */ |
*flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); |
#else |
(void) ca_crl; |
#endif |
/* prepare for next iteration */ |
child = parent; |
parent = NULL; |
child_is_trusted = parent_is_trusted; |
signature_is_good = 0; |
} |
} |
/* |
* Check for CN match |
*/ |
static int x509_crt_check_cn( const mbedtls_x509_buf *name, |
const char *cn, size_t cn_len ) |
{ |
/* try exact match */ |
if( name->len == cn_len && |
x509_memcasecmp( cn, name->p, cn_len ) == 0 ) |
{ |
return( 0 ); |
} |
/* try wildcard match */ |
if( x509_check_wildcard( cn, name ) == 0 ) |
{ |
return( 0 ); |
} |
return( -1 ); |
} |
/* |
* Verify the requested CN - only call this if cn is not NULL! |
*/ |
static void x509_crt_verify_name( const mbedtls_x509_crt *crt, |
const char *cn, |
uint32_t *flags ) |
{ |
const mbedtls_x509_name *name; |
const mbedtls_x509_sequence *cur; |
size_t cn_len = strlen( cn ); |
if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) |
{ |
for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) |
{ |
if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 ) |
break; |
} |
if( cur == NULL ) |
*flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; |
} |
else |
{ |
for( name = &crt->subject; name != NULL; name = name->next ) |
{ |
if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && |
x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) |
{ |
break; |
} |
} |
if( name == NULL ) |
*flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; |
} |
} |
/* |
* Merge the flags for all certs in the chain, after calling callback |
*/ |
static int x509_crt_merge_flags_with_cb( |
uint32_t *flags, |
const mbedtls_x509_crt_verify_chain *ver_chain, |
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), |
void *p_vrfy ) |
{ |
int ret; |
unsigned i; |
uint32_t cur_flags; |
const mbedtls_x509_crt_verify_chain_item *cur; |
for( i = ver_chain->len; i != 0; --i ) |
{ |
cur = &ver_chain->items[i-1]; |
cur_flags = cur->flags; |
if( NULL != f_vrfy ) |
if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) |
return( ret ); |
*flags |= cur_flags; |
} |
return( 0 ); |
} |
/* |
* Verify the certificate validity (default profile, not restartable) |
*/ |
int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, |
mbedtls_x509_crt *trust_ca, |
mbedtls_x509_crl *ca_crl, |
const char *cn, uint32_t *flags, |
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), |
void *p_vrfy ) |
{ |
return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, |
&mbedtls_x509_crt_profile_default, cn, flags, |
f_vrfy, p_vrfy, NULL ) ); |
} |
/* |
* Verify the certificate validity (user-chosen profile, not restartable) |
*/ |
int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, |
mbedtls_x509_crt *trust_ca, |
mbedtls_x509_crl *ca_crl, |
const mbedtls_x509_crt_profile *profile, |
const char *cn, uint32_t *flags, |
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), |
void *p_vrfy ) |
{ |
return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, |
profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); |
} |
/* |
* Verify the certificate validity, with profile, restartable version |
* |
* This function: |
* - checks the requested CN (if any) |
* - checks the type and size of the EE cert's key, |
* as that isn't done as part of chain building/verification currently |
* - builds and verifies the chain |
* - then calls the callback and merges the flags |
*/ |
int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, |
mbedtls_x509_crt *trust_ca, |
mbedtls_x509_crl *ca_crl, |
const mbedtls_x509_crt_profile *profile, |
const char *cn, uint32_t *flags, |
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), |
void *p_vrfy, |
mbedtls_x509_crt_restart_ctx *rs_ctx ) |
{ |
int ret; |
mbedtls_pk_type_t pk_type; |
mbedtls_x509_crt_verify_chain ver_chain; |
uint32_t ee_flags; |
*flags = 0; |
ee_flags = 0; |
x509_crt_verify_chain_reset( &ver_chain ); |
if( profile == NULL ) |
{ |
ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; |
goto exit; |
} |
/* check name if requested */ |
if( cn != NULL ) |
x509_crt_verify_name( crt, cn, &ee_flags ); |
/* Check the type and size of the key */ |
pk_type = mbedtls_pk_get_type( &crt->pk ); |
if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) |
ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; |
if( x509_profile_check_key( profile, &crt->pk ) != 0 ) |
ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; |
/* Check the chain */ |
ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, |
&ver_chain, rs_ctx ); |
if( ret != 0 ) |
goto exit; |
/* Merge end-entity flags */ |
ver_chain.items[0].flags |= ee_flags; |
/* Build final flags, calling callback on the way if any */ |
ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); |
exit: |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) |
mbedtls_x509_crt_restart_free( rs_ctx ); |
#endif |
/* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by |
* the SSL module for authmode optional, but non-zero return from the |
* callback means a fatal error so it shouldn't be ignored */ |
if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) |
ret = MBEDTLS_ERR_X509_FATAL_ERROR; |
if( ret != 0 ) |
{ |
*flags = (uint32_t) -1; |
return( ret ); |
} |
if( *flags != 0 ) |
return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); |
return( 0 ); |
} |
/* |
* Initialize a certificate chain |
*/ |
void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) |
{ |
memset( crt, 0, sizeof(mbedtls_x509_crt) ); |
} |
/* |
* Unallocate all certificate data |
*/ |
void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) |
{ |
mbedtls_x509_crt *cert_cur = crt; |
mbedtls_x509_crt *cert_prv; |
mbedtls_x509_name *name_cur; |
mbedtls_x509_name *name_prv; |
mbedtls_x509_sequence *seq_cur; |
mbedtls_x509_sequence *seq_prv; |
if( crt == NULL ) |
return; |
do |
{ |
mbedtls_pk_free( &cert_cur->pk ); |
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
mbedtls_free( cert_cur->sig_opts ); |
#endif |
name_cur = cert_cur->issuer.next; |
while( name_cur != NULL ) |
{ |
name_prv = name_cur; |
name_cur = name_cur->next; |
mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); |
mbedtls_free( name_prv ); |
} |
name_cur = cert_cur->subject.next; |
while( name_cur != NULL ) |
{ |
name_prv = name_cur; |
name_cur = name_cur->next; |
mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); |
mbedtls_free( name_prv ); |
} |
seq_cur = cert_cur->ext_key_usage.next; |
while( seq_cur != NULL ) |
{ |
seq_prv = seq_cur; |
seq_cur = seq_cur->next; |
mbedtls_platform_zeroize( seq_prv, |
sizeof( mbedtls_x509_sequence ) ); |
mbedtls_free( seq_prv ); |
} |
seq_cur = cert_cur->subject_alt_names.next; |
while( seq_cur != NULL ) |
{ |
seq_prv = seq_cur; |
seq_cur = seq_cur->next; |
mbedtls_platform_zeroize( seq_prv, |
sizeof( mbedtls_x509_sequence ) ); |
mbedtls_free( seq_prv ); |
} |
if( cert_cur->raw.p != NULL ) |
{ |
mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); |
mbedtls_free( cert_cur->raw.p ); |
} |
cert_cur = cert_cur->next; |
} |
while( cert_cur != NULL ); |
cert_cur = crt; |
do |
{ |
cert_prv = cert_cur; |
cert_cur = cert_cur->next; |
mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); |
if( cert_prv != crt ) |
mbedtls_free( cert_prv ); |
} |
while( cert_cur != NULL ); |
} |
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
/* |
* Initialize a restart context |
*/ |
void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) |
{ |
mbedtls_pk_restart_init( &ctx->pk ); |
ctx->parent = NULL; |
ctx->fallback_parent = NULL; |
ctx->fallback_signature_is_good = 0; |
ctx->parent_is_trusted = -1; |
ctx->in_progress = x509_crt_rs_none; |
ctx->self_cnt = 0; |
x509_crt_verify_chain_reset( &ctx->ver_chain ); |
} |
/* |
* Free the components of a restart context |
*/ |
void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_pk_restart_free( &ctx->pk ); |
mbedtls_x509_crt_restart_init( ctx ); |
} |
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ |
#endif /* MBEDTLS_X509_CRT_PARSE_C */ |
/programs/develop/libraries/kos_mbedtls/library/x509_csr.c |
---|
0,0 → 1,421 |
/* |
* X.509 Certificate Signing Request (CSR) parsing |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* The ITU-T X.509 standard defines a certificate format for PKI. |
* |
* http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) |
* http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) |
* http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) |
* |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf |
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_X509_CSR_PARSE_C) |
#include "mbedtls/x509_csr.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PEM_PARSE_C) |
#include "mbedtls/pem.h" |
#endif |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdlib.h> |
#include <stdio.h> |
#define mbedtls_free free |
#define mbedtls_calloc calloc |
#define mbedtls_snprintf snprintf |
#endif |
#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) |
#include <stdio.h> |
#endif |
/* |
* Version ::= INTEGER { v1(0) } |
*/ |
static int x509_csr_get_version( unsigned char **p, |
const unsigned char *end, |
int *ver ) |
{ |
int ret; |
if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) |
{ |
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) |
{ |
*ver = 0; |
return( 0 ); |
} |
return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); |
} |
return( 0 ); |
} |
/* |
* Parse a CSR in DER format |
*/ |
int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, |
const unsigned char *buf, size_t buflen ) |
{ |
int ret; |
size_t len; |
unsigned char *p, *end; |
mbedtls_x509_buf sig_params; |
memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); |
/* |
* Check for valid input |
*/ |
if( csr == NULL || buf == NULL || buflen == 0 ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
mbedtls_x509_csr_init( csr ); |
/* |
* first copy the raw DER data |
*/ |
p = mbedtls_calloc( 1, len = buflen ); |
if( p == NULL ) |
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); |
memcpy( p, buf, buflen ); |
csr->raw.p = p; |
csr->raw.len = len; |
end = p + len; |
/* |
* CertificationRequest ::= SEQUENCE { |
* certificationRequestInfo CertificationRequestInfo, |
* signatureAlgorithm AlgorithmIdentifier, |
* signature BIT STRING |
* } |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT ); |
} |
if( len != (size_t) ( end - p ) ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
/* |
* CertificationRequestInfo ::= SEQUENCE { |
*/ |
csr->cri.p = p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
end = p + len; |
csr->cri.len = end - csr->cri.p; |
/* |
* Version ::= INTEGER { v1(0) } |
*/ |
if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( ret ); |
} |
if( csr->version != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); |
} |
csr->version++; |
/* |
* subject Name |
*/ |
csr->subject_raw.p = p; |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( ret ); |
} |
csr->subject_raw.len = p - csr->subject_raw.p; |
/* |
* subjectPKInfo SubjectPublicKeyInfo |
*/ |
if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( ret ); |
} |
/* |
* attributes [0] Attributes |
* |
* The list of possible attributes is open-ended, though RFC 2985 |
* (PKCS#9) defines a few in section 5.4. We currently don't support any, |
* so we just ignore them. This is a safe thing to do as the worst thing |
* that could happen is that we issue a certificate that does not match |
* the requester's expectations - this cannot cause a violation of our |
* signature policies. |
*/ |
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); |
} |
p += len; |
end = csr->raw.p + csr->raw.len; |
/* |
* signatureAlgorithm AlgorithmIdentifier, |
* signature BIT STRING |
*/ |
if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( ret ); |
} |
if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, |
&csr->sig_md, &csr->sig_pk, |
&csr->sig_opts ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); |
} |
if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( ret ); |
} |
if( p != end ) |
{ |
mbedtls_x509_csr_free( csr ); |
return( MBEDTLS_ERR_X509_INVALID_FORMAT + |
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); |
} |
return( 0 ); |
} |
/* |
* Parse a CSR, allowing for PEM or raw DER encoding |
*/ |
int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) |
{ |
#if defined(MBEDTLS_PEM_PARSE_C) |
int ret; |
size_t use_len; |
mbedtls_pem_context pem; |
#endif |
/* |
* Check for valid input |
*/ |
if( csr == NULL || buf == NULL || buflen == 0 ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
#if defined(MBEDTLS_PEM_PARSE_C) |
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ |
if( buf[buflen - 1] == '\0' ) |
{ |
mbedtls_pem_init( &pem ); |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN CERTIFICATE REQUEST-----", |
"-----END CERTIFICATE REQUEST-----", |
buf, NULL, 0, &use_len ); |
if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
{ |
ret = mbedtls_pem_read_buffer( &pem, |
"-----BEGIN NEW CERTIFICATE REQUEST-----", |
"-----END NEW CERTIFICATE REQUEST-----", |
buf, NULL, 0, &use_len ); |
} |
if( ret == 0 ) |
{ |
/* |
* Was PEM encoded, parse the result |
*/ |
ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); |
} |
mbedtls_pem_free( &pem ); |
if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) |
return( ret ); |
} |
#endif /* MBEDTLS_PEM_PARSE_C */ |
return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); |
} |
#if defined(MBEDTLS_FS_IO) |
/* |
* Load a CSR into the structure |
*/ |
int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) |
{ |
int ret; |
size_t n; |
unsigned char *buf; |
if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) |
return( ret ); |
ret = mbedtls_x509_csr_parse( csr, buf, n ); |
mbedtls_platform_zeroize( buf, n ); |
mbedtls_free( buf ); |
return( ret ); |
} |
#endif /* MBEDTLS_FS_IO */ |
#define BEFORE_COLON 14 |
#define BC "14" |
/* |
* Return an informational string about the CSR. |
*/ |
int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, |
const mbedtls_x509_csr *csr ) |
{ |
int ret; |
size_t n; |
char *p; |
char key_size_str[BEFORE_COLON]; |
p = buf; |
n = size; |
ret = mbedtls_snprintf( p, n, "%sCSR version : %d", |
prefix, csr->version ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, |
csr->sig_opts ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, |
mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) |
{ |
return( ret ); |
} |
ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, |
(int) mbedtls_pk_get_bitlen( &csr->pk ) ); |
MBEDTLS_X509_SAFE_SNPRINTF; |
return( (int) ( size - n ) ); |
} |
/* |
* Initialize a CSR |
*/ |
void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) |
{ |
memset( csr, 0, sizeof(mbedtls_x509_csr) ); |
} |
/* |
* Unallocate all CSR data |
*/ |
void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) |
{ |
mbedtls_x509_name *name_cur; |
mbedtls_x509_name *name_prv; |
if( csr == NULL ) |
return; |
mbedtls_pk_free( &csr->pk ); |
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
mbedtls_free( csr->sig_opts ); |
#endif |
name_cur = csr->subject.next; |
while( name_cur != NULL ) |
{ |
name_prv = name_cur; |
name_cur = name_cur->next; |
mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); |
mbedtls_free( name_prv ); |
} |
if( csr->raw.p != NULL ) |
{ |
mbedtls_platform_zeroize( csr->raw.p, csr->raw.len ); |
mbedtls_free( csr->raw.p ); |
} |
mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) ); |
} |
#endif /* MBEDTLS_X509_CSR_PARSE_C */ |
/programs/develop/libraries/kos_mbedtls/library/x509write_crt.c |
---|
0,0 → 1,524 |
/* |
* X.509 certificate writing |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* References: |
* - certificates: RFC 5280, updated by RFC 6818 |
* - CSRs: PKCS#10 v1.7 aka RFC 2986 |
* - attributes: PKCS#9 v2.0 aka RFC 2985 |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_X509_CRT_WRITE_C) |
#include "mbedtls/x509_crt.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/asn1write.h" |
#include "mbedtls/sha1.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_PEM_WRITE_C) |
#include "mbedtls/pem.h" |
#endif /* MBEDTLS_PEM_WRITE_C */ |
/* |
* For the currently used signature algorithms the buffer to store any signature |
* must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) |
*/ |
#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE |
#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN |
#else |
#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE |
#endif |
void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); |
mbedtls_mpi_init( &ctx->serial ); |
ctx->version = MBEDTLS_X509_CRT_VERSION_3; |
} |
void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) |
{ |
mbedtls_mpi_free( &ctx->serial ); |
mbedtls_asn1_free_named_data_list( &ctx->subject ); |
mbedtls_asn1_free_named_data_list( &ctx->issuer ); |
mbedtls_asn1_free_named_data_list( &ctx->extensions ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); |
} |
void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) |
{ |
ctx->version = version; |
} |
void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) |
{ |
ctx->md_alg = md_alg; |
} |
void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) |
{ |
ctx->subject_key = key; |
} |
void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) |
{ |
ctx->issuer_key = key; |
} |
int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, |
const char *subject_name ) |
{ |
return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); |
} |
int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, |
const char *issuer_name ) |
{ |
return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); |
} |
int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) |
{ |
int ret; |
if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) |
return( ret ); |
return( 0 ); |
} |
int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, |
const char *not_after ) |
{ |
if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || |
strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) |
{ |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
} |
strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); |
strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); |
ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; |
ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; |
return( 0 ); |
} |
int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, |
const char *oid, size_t oid_len, |
int critical, |
const unsigned char *val, size_t val_len ) |
{ |
return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, |
critical, val, val_len ); |
} |
int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, |
int is_ca, int max_pathlen ) |
{ |
int ret; |
unsigned char buf[9]; |
unsigned char *c = buf + sizeof(buf); |
size_t len = 0; |
memset( buf, 0, sizeof(buf) ); |
if( is_ca && max_pathlen > 127 ) |
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); |
if( is_ca ) |
{ |
if( max_pathlen >= 0 ) |
{ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), |
0, buf + sizeof(buf) - len, len ); |
} |
#if defined(MBEDTLS_SHA1_C) |
int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) |
{ |
int ret; |
unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ |
unsigned char *c = buf + sizeof(buf); |
size_t len = 0; |
memset( buf, 0, sizeof(buf) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); |
ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, |
buf + sizeof( buf ) - 20 ); |
if( ret != 0 ) |
return( ret ); |
c = buf + sizeof( buf ) - 20; |
len = 20; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); |
return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), |
0, buf + sizeof(buf) - len, len ); |
} |
int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) |
{ |
int ret; |
unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ |
unsigned char *c = buf + sizeof( buf ); |
size_t len = 0; |
memset( buf, 0, sizeof(buf) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); |
ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, |
buf + sizeof( buf ) - 20 ); |
if( ret != 0 ) |
return( ret ); |
c = buf + sizeof( buf ) - 20; |
len = 20; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), |
0, buf + sizeof( buf ) - len, len ); |
} |
#endif /* MBEDTLS_SHA1_C */ |
static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring, |
size_t bit_offset ) |
{ |
size_t unused_bits; |
/* Count the unused bits removing trailing 0s */ |
for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) |
if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) |
break; |
return( unused_bits ); |
} |
int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, |
unsigned int key_usage ) |
{ |
unsigned char buf[4], ku; |
unsigned char *c; |
int ret; |
size_t unused_bits; |
const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | |
MBEDTLS_X509_KU_NON_REPUDIATION | |
MBEDTLS_X509_KU_KEY_ENCIPHERMENT | |
MBEDTLS_X509_KU_DATA_ENCIPHERMENT | |
MBEDTLS_X509_KU_KEY_AGREEMENT | |
MBEDTLS_X509_KU_KEY_CERT_SIGN | |
MBEDTLS_X509_KU_CRL_SIGN; |
/* Check that nothing other than the allowed flags is set */ |
if( ( key_usage & ~allowed_bits ) != 0 ) |
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); |
c = buf + 4; |
ku = (unsigned char)key_usage; |
unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 ); |
ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits ); |
if( ret < 0 ) |
return( ret ); |
else if( ret < 3 || ret > 4 ) |
return( MBEDTLS_ERR_X509_INVALID_FORMAT ); |
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), |
1, c, (size_t)ret ); |
if( ret != 0 ) |
return( ret ); |
return( 0 ); |
} |
int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, |
unsigned char ns_cert_type ) |
{ |
unsigned char buf[4]; |
unsigned char *c; |
size_t unused_bits; |
int ret; |
c = buf + 4; |
unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); |
ret = mbedtls_asn1_write_bitstring( &c, |
buf, |
&ns_cert_type, |
8 - unused_bits ); |
if( ret < 3 || ret > 4 ) |
return( ret ); |
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), |
0, c, (size_t)ret ); |
if( ret != 0 ) |
return( ret ); |
return( 0 ); |
} |
static int x509_write_time( unsigned char **p, unsigned char *start, |
const char *t, size_t size ) |
{ |
int ret; |
size_t len = 0; |
/* |
* write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) |
*/ |
if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) |
{ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, |
(const unsigned char *) t + 2, |
size - 2 ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); |
} |
else |
{ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, |
(const unsigned char *) t, |
size ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); |
} |
return( (int) len ); |
} |
int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
const char *sig_oid; |
size_t sig_oid_len = 0; |
unsigned char *c, *c2; |
unsigned char hash[64]; |
unsigned char sig[SIGNATURE_MAX_SIZE]; |
unsigned char tmp_buf[2048]; |
size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; |
size_t len = 0; |
mbedtls_pk_type_t pk_alg; |
/* |
* Prepare data to be signed in tmp_buf |
*/ |
c = tmp_buf + sizeof( tmp_buf ); |
/* Signature algorithm needed in TBS, and later for actual signature */ |
/* There's no direct way of extracting a signature algorithm |
* (represented as an element of mbedtls_pk_type_t) from a PK instance. */ |
if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) |
pk_alg = MBEDTLS_PK_RSA; |
else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) |
pk_alg = MBEDTLS_PK_ECDSA; |
else |
return( MBEDTLS_ERR_X509_INVALID_ALG ); |
if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, |
&sig_oid, &sig_oid_len ) ) != 0 ) |
{ |
return( ret ); |
} |
/* |
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
*/ |
/* Only for v3 */ |
if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) |
{ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | |
MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); |
} |
/* |
* SubjectPublicKeyInfo |
*/ |
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, |
tmp_buf, c - tmp_buf ) ); |
c -= pub_len; |
len += pub_len; |
/* |
* Subject ::= Name |
*/ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); |
/* |
* Validity ::= SEQUENCE { |
* notBefore Time, |
* notAfter Time } |
*/ |
sub_len = 0; |
MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, |
MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); |
MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, |
MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); |
len += sub_len; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
/* |
* Issuer ::= Name |
*/ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); |
/* |
* Signature ::= AlgorithmIdentifier |
*/ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, |
sig_oid, strlen( sig_oid ), 0 ) ); |
/* |
* Serial ::= INTEGER |
*/ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); |
/* |
* Version ::= INTEGER { v1(0), v2(1), v3(2) } |
*/ |
/* Can be omitted for v1 */ |
if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) |
{ |
sub_len = 0; |
MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); |
len += sub_len; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | |
MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
/* |
* Make signature |
*/ |
if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, |
len, hash ) ) != 0 ) |
{ |
return( ret ); |
} |
if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, |
f_rng, p_rng ) ) != 0 ) |
{ |
return( ret ); |
} |
/* |
* Write data to output buffer |
*/ |
c2 = buf + size; |
MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, |
sig_oid, sig_oid_len, sig, sig_len ) ); |
if( len > (size_t)( c2 - buf ) ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
c2 -= len; |
memcpy( c2, c, len ); |
len += sig_and_oid_len; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return( (int) len ); |
} |
#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" |
#define PEM_END_CRT "-----END CERTIFICATE-----\n" |
#if defined(MBEDTLS_PEM_WRITE_C) |
int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
unsigned char output_buf[4096]; |
size_t olen = 0; |
if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), |
f_rng, p_rng ) ) < 0 ) |
{ |
return( ret ); |
} |
if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, |
output_buf + sizeof(output_buf) - ret, |
ret, buf, size, &olen ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_PEM_WRITE_C */ |
#endif /* MBEDTLS_X509_CRT_WRITE_C */ |
/programs/develop/libraries/kos_mbedtls/library/x509write_csr.c |
---|
0,0 → 1,304 |
/* |
* X.509 Certificate Signing Request writing |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
/* |
* References: |
* - CSRs: PKCS#10 v1.7 aka RFC 2986 |
* - attributes: PKCS#9 v2.0 aka RFC 2985 |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_X509_CSR_WRITE_C) |
#include "mbedtls/x509_csr.h" |
#include "mbedtls/oid.h" |
#include "mbedtls/asn1write.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#include <stdlib.h> |
#if defined(MBEDTLS_PEM_WRITE_C) |
#include "mbedtls/pem.h" |
#endif |
/* |
* For the currently used signature algorithms the buffer to store any signature |
* must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) |
*/ |
#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE |
#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN |
#else |
#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE |
#endif |
void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); |
} |
void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) |
{ |
mbedtls_asn1_free_named_data_list( &ctx->subject ); |
mbedtls_asn1_free_named_data_list( &ctx->extensions ); |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); |
} |
void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) |
{ |
ctx->md_alg = md_alg; |
} |
void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) |
{ |
ctx->key = key; |
} |
int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, |
const char *subject_name ) |
{ |
return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); |
} |
int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, |
const char *oid, size_t oid_len, |
const unsigned char *val, size_t val_len ) |
{ |
return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, |
0, val, val_len ); |
} |
static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring, |
size_t bit_offset ) |
{ |
size_t unused_bits; |
/* Count the unused bits removing trailing 0s */ |
for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) |
if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) |
break; |
return( unused_bits ); |
} |
int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) |
{ |
unsigned char buf[4]; |
unsigned char *c; |
size_t unused_bits; |
int ret; |
c = buf + 4; |
unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 ); |
ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits ); |
if( ret < 0 ) |
return( ret ); |
else if( ret < 3 || ret > 4 ) |
return( MBEDTLS_ERR_X509_INVALID_FORMAT ); |
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), |
c, (size_t)ret ); |
if( ret != 0 ) |
return( ret ); |
return( 0 ); |
} |
int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, |
unsigned char ns_cert_type ) |
{ |
unsigned char buf[4]; |
unsigned char *c; |
size_t unused_bits; |
int ret; |
c = buf + 4; |
unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); |
ret = mbedtls_asn1_write_bitstring( &c, |
buf, |
&ns_cert_type, |
8 - unused_bits ); |
if( ret < 0 ) |
return( ret ); |
else if( ret < 3 || ret > 4 ) |
return( ret ); |
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), |
c, (size_t)ret ); |
if( ret != 0 ) |
return( ret ); |
return( 0 ); |
} |
int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
const char *sig_oid; |
size_t sig_oid_len = 0; |
unsigned char *c, *c2; |
unsigned char hash[64]; |
unsigned char sig[SIGNATURE_MAX_SIZE]; |
unsigned char tmp_buf[2048]; |
size_t pub_len = 0, sig_and_oid_len = 0, sig_len; |
size_t len = 0; |
mbedtls_pk_type_t pk_alg; |
/* |
* Prepare data to be signed in tmp_buf |
*/ |
c = tmp_buf + sizeof( tmp_buf ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); |
if( len ) |
{ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SET ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, |
MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
} |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); |
MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, |
tmp_buf, c - tmp_buf ) ); |
c -= pub_len; |
len += pub_len; |
/* |
* Subject ::= Name |
*/ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); |
/* |
* Version ::= INTEGER { v1(0), v2(1), v3(2) } |
*/ |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
/* |
* Prepare signature |
*/ |
ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); |
if( ret != 0 ) |
return( ret ); |
if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, |
f_rng, p_rng ) ) != 0 ) |
{ |
return( ret ); |
} |
if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) |
pk_alg = MBEDTLS_PK_RSA; |
else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) |
pk_alg = MBEDTLS_PK_ECDSA; |
else |
return( MBEDTLS_ERR_X509_INVALID_ALG ); |
if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, |
&sig_oid, &sig_oid_len ) ) != 0 ) |
{ |
return( ret ); |
} |
/* |
* Write data to output buffer |
*/ |
c2 = buf + size; |
MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, |
sig_oid, sig_oid_len, sig, sig_len ) ); |
if( len > (size_t)( c2 - buf ) ) |
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
c2 -= len; |
memcpy( c2, c, len ); |
len += sig_and_oid_len; |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); |
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | |
MBEDTLS_ASN1_SEQUENCE ) ); |
return( (int) len ); |
} |
#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" |
#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" |
#if defined(MBEDTLS_PEM_WRITE_C) |
int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, |
int (*f_rng)(void *, unsigned char *, size_t), |
void *p_rng ) |
{ |
int ret; |
unsigned char output_buf[4096]; |
size_t olen = 0; |
if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), |
f_rng, p_rng ) ) < 0 ) |
{ |
return( ret ); |
} |
if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, |
output_buf + sizeof(output_buf) - ret, |
ret, buf, size, &olen ) ) != 0 ) |
{ |
return( ret ); |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_PEM_WRITE_C */ |
#endif /* MBEDTLS_X509_CSR_WRITE_C */ |
/programs/develop/libraries/kos_mbedtls/library/xtea.c |
---|
0,0 → 1,279 |
/* |
* An 32-bit implementation of the XTEA algorithm |
* |
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved |
* SPDX-License-Identifier: GPL-2.0 |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or |
* (at your option) any later version. |
* |
* This program is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* GNU General Public License for more details. |
* |
* You should have received a copy of the GNU General Public License along |
* with this program; if not, write to the Free Software Foundation, Inc., |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
* |
* This file is part of mbed TLS (https://tls.mbed.org) |
*/ |
#if !defined(MBEDTLS_CONFIG_FILE) |
#include "mbedtls/config.h" |
#else |
#include MBEDTLS_CONFIG_FILE |
#endif |
#if defined(MBEDTLS_XTEA_C) |
#include "mbedtls/xtea.h" |
#include "mbedtls/platform_util.h" |
#include <string.h> |
#if defined(MBEDTLS_SELF_TEST) |
#if defined(MBEDTLS_PLATFORM_C) |
#include "mbedtls/platform.h" |
#else |
#include <stdio.h> |
#define mbedtls_printf printf |
#endif /* MBEDTLS_PLATFORM_C */ |
#endif /* MBEDTLS_SELF_TEST */ |
#if !defined(MBEDTLS_XTEA_ALT) |
/* |
* 32-bit integer manipulation macros (big endian) |
*/ |
#ifndef GET_UINT32_BE |
#define GET_UINT32_BE(n,b,i) \ |
{ \ |
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 3] ); \ |
} |
#endif |
#ifndef PUT_UINT32_BE |
#define PUT_UINT32_BE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) ); \ |
} |
#endif |
void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) |
{ |
memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); |
} |
void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) |
{ |
if( ctx == NULL ) |
return; |
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); |
} |
/* |
* XTEA key schedule |
*/ |
void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) |
{ |
int i; |
memset( ctx, 0, sizeof(mbedtls_xtea_context) ); |
for( i = 0; i < 4; i++ ) |
{ |
GET_UINT32_BE( ctx->k[i], key, i << 2 ); |
} |
} |
/* |
* XTEA encrypt function |
*/ |
int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, |
const unsigned char input[8], unsigned char output[8]) |
{ |
uint32_t *k, v0, v1, i; |
k = ctx->k; |
GET_UINT32_BE( v0, input, 0 ); |
GET_UINT32_BE( v1, input, 4 ); |
if( mode == MBEDTLS_XTEA_ENCRYPT ) |
{ |
uint32_t sum = 0, delta = 0x9E3779B9; |
for( i = 0; i < 32; i++ ) |
{ |
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); |
sum += delta; |
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); |
} |
} |
else /* MBEDTLS_XTEA_DECRYPT */ |
{ |
uint32_t delta = 0x9E3779B9, sum = delta * 32; |
for( i = 0; i < 32; i++ ) |
{ |
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); |
sum -= delta; |
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); |
} |
} |
PUT_UINT32_BE( v0, output, 0 ); |
PUT_UINT32_BE( v1, output, 4 ); |
return( 0 ); |
} |
#if defined(MBEDTLS_CIPHER_MODE_CBC) |
/* |
* XTEA-CBC buffer encryption/decryption |
*/ |
int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, |
unsigned char iv[8], const unsigned char *input, |
unsigned char *output) |
{ |
int i; |
unsigned char temp[8]; |
if( length % 8 ) |
return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); |
if( mode == MBEDTLS_XTEA_DECRYPT ) |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, 8 ); |
mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); |
for( i = 0; i < 8; i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, 8 ); |
input += 8; |
output += 8; |
length -= 8; |
} |
} |
else |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < 8; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); |
memcpy( iv, output, 8 ); |
input += 8; |
output += 8; |
length -= 8; |
} |
} |
return( 0 ); |
} |
#endif /* MBEDTLS_CIPHER_MODE_CBC */ |
#endif /* !MBEDTLS_XTEA_ALT */ |
#if defined(MBEDTLS_SELF_TEST) |
/* |
* XTEA tests vectors (non-official) |
*/ |
static const unsigned char xtea_test_key[6][16] = |
{ |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, |
0x0c, 0x0d, 0x0e, 0x0f }, |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, |
0x0c, 0x0d, 0x0e, 0x0f }, |
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, |
0x0c, 0x0d, 0x0e, 0x0f }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00 }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00 }, |
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00 } |
}; |
static const unsigned char xtea_test_pt[6][8] = |
{ |
{ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, |
{ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, |
{ 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, |
{ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, |
{ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, |
{ 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } |
}; |
static const unsigned char xtea_test_ct[6][8] = |
{ |
{ 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, |
{ 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, |
{ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, |
{ 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, |
{ 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, |
{ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } |
}; |
/* |
* Checkup routine |
*/ |
int mbedtls_xtea_self_test( int verbose ) |
{ |
int i, ret = 0; |
unsigned char buf[8]; |
mbedtls_xtea_context ctx; |
mbedtls_xtea_init( &ctx ); |
for( i = 0; i < 6; i++ ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( " XTEA test #%d: ", i + 1 ); |
memcpy( buf, xtea_test_pt[i], 8 ); |
mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); |
mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); |
if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) |
{ |
if( verbose != 0 ) |
mbedtls_printf( "failed\n" ); |
ret = 1; |
goto exit; |
} |
if( verbose != 0 ) |
mbedtls_printf( "passed\n" ); |
} |
if( verbose != 0 ) |
mbedtls_printf( "\n" ); |
exit: |
mbedtls_xtea_free( &ctx ); |
return( ret ); |
} |
#endif /* MBEDTLS_SELF_TEST */ |
#endif /* MBEDTLS_XTEA_C */ |