/* * MbedTLS Source Code Library Source */ #include "mbedtls.h" #if ME_COM_MBEDTLS /********* Start of file library/aes.c ************/ /* * FIPS-197 compliant AES implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_AES_C) #include #if defined(MBEDTLS_PADLOCK_C) #endif #if defined(MBEDTLS_AESNI_C) #endif #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_AES_ALT) /* Amalgamated Release Mappings */ #define FSb AESFSb /* Implementation that should never be optimized out by the compiler */ static void aes_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 #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 #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 #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 #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]; static uint32_t FT1[256]; static uint32_t FT2[256]; static uint32_t FT3[256]; /* * Reverse S-box & tables */ static unsigned char RSb[256]; static uint32_t RT0[256]; static uint32_t RT1[256]; static uint32_t RT2[256]; static uint32_t RT3[256]; /* * 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 ); FT1[i] = ROTL8( FT0[i] ); FT2[i] = ROTL8( FT1[i] ); FT3[i] = ROTL8( FT2[i] ); 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 ); RT1[i] = ROTL8( RT0[i] ); RT2[i] = ROTL8( RT1[i] ); RT3[i] = ROTL8( RT2[i] ); } } #endif /* MBEDTLS_AES_ROM_TABLES */ void mbedtls_aes_init( mbedtls_aes_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_aes_context ) ); } void mbedtls_aes_free( mbedtls_aes_context *ctx ) { if( ctx == NULL ) return; aes_zeroize( ctx, sizeof( mbedtls_aes_context ) ); } /* * 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; #if !defined(MBEDTLS_AES_ROM_TABLES) if( aes_init_done == 0 ) { aes_gen_tables(); aes_init_done = 1; } #endif 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_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; 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++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; } } *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; exit: mbedtls_aes_free( &cty ); return( ret ); } #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ { \ X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ FT3[ ( Y3 >> 24 ) & 0xFF ]; \ \ X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ FT3[ ( Y0 >> 24 ) & 0xFF ]; \ \ X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ FT3[ ( Y1 >> 24 ) & 0xFF ]; \ \ X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ FT3[ ( Y2 >> 24 ) & 0xFF ]; \ } #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ { \ X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ RT3[ ( Y1 >> 24 ) & 0xFF ]; \ \ X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ RT3[ ( Y2 >> 24 ) & 0xFF ]; \ \ X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ RT3[ ( Y3 >> 24 ) & 0xFF ]; \ \ X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ RT3[ ( Y0 >> 24 ) & 0xFF ]; \ } /* * AES-ECB block encryption */ #if !defined(MBEDTLS_AES_ENCRYPT_ALT) void mbedtls_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 ); } #endif /* !MBEDTLS_AES_ENCRYPT_ALT */ /* * AES-ECB block decryption */ #if !defined(MBEDTLS_AES_DECRYPT_ALT) void mbedtls_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 ); } #endif /* !MBEDTLS_AES_DECRYPT_ALT */ /* * 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] ) { #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 ) mbedtls_aes_encrypt( ctx, input, output ); else mbedtls_aes_decrypt( ctx, input, output ); return( 0 ); } #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]; 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_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 = *iv_off; 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]; 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_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 = *nc_off; 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_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 */ /* * Checkup routine */ int mbedtls_aes_self_test( int verbose ) { int ret = 0, i, j, u, v; unsigned char key[32]; unsigned char buf[64]; unsigned char iv[16]; #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) size_t offset; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) int len; 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; v = i & 1; if( verbose != 0 ) mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); memset( buf, 0, 16 ); if( v == MBEDTLS_AES_DECRYPT ) { mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); for( j = 0; j < 10000; j++ ) mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); ret = 1; goto exit; } } else { mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); for( j = 0; j < 10000; j++ ) mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 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( " AES-CBC-%3d (%s): ", 128 + u * 64, ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); memset( iv , 0, 16 ); memset( prv, 0, 16 ); memset( buf, 0, 16 ); if( v == MBEDTLS_AES_DECRYPT ) { mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); for( j = 0; j < 10000; j++ ) mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); ret = 1; goto exit; } } else { mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); for( j = 0; j < 10000; j++ ) { unsigned char tmp[16]; mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); memcpy( tmp, prv, 16 ); memcpy( prv, buf, 16 ); memcpy( buf, tmp, 16 ); } if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 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" ); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * CFB128 mode */ for( i = 0; i < 6; i++ ) { u = i >> 1; v = i & 1; if( verbose != 0 ) mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); memcpy( iv, aes_test_cfb128_iv, 16 ); memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); offset = 0; mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); if( v == MBEDTLS_AES_DECRYPT ) { memcpy( buf, aes_test_cfb128_ct[u], 64 ); mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); ret = 1; goto exit; } } else { memcpy( buf, aes_test_cfb128_pt, 64 ); mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 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" ); #endif /* MBEDTLS_CIPHER_MODE_CFB */ #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( " AES-CTR-128 (%s): ", ( v == 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; mbedtls_aes_setkey_enc( &ctx, key, 128 ); if( v == MBEDTLS_AES_DECRYPT ) { len = aes_test_ctr_len[u]; memcpy( buf, aes_test_ctr_ct[u], len ); mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); ret = 1; goto exit; } } else { len = aes_test_ctr_len[u]; memcpy( buf, aes_test_ctr_pt[u], len ); mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf ); if( memcmp( buf, aes_test_ctr_ct[u], len ) != 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" ); #endif /* MBEDTLS_CIPHER_MODE_CTR */ ret = 0; exit: mbedtls_aes_free( &ctx ); return( ret ); } #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #undef FSb #endif /* MBEDTLS_AES_C */ /********* Start of file library/aesni.c ************/ /* * AES-NI support functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_AESNI_C) #include #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 "addq $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 "addq $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 "addq $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 */ /********* Start of file library/arc4.c ************/ /* * An implementation of the ARCFOUR algorithm * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_ARC4_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_ARC4_ALT) /* Implementation that should never be optimized out by the compiler */ static void arc4_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } 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; arc4_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 */ /********* Start of file library/asn1parse.c ************/ /* * Generic ASN.1 parsing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_ASN1_PARSE_C) #include #if defined(MBEDTLS_BIGNUM_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif /* Implementation that should never be optimized out by the compiler */ static void asn1_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 > 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 " */ 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_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 ) { asn1_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 ); asn1_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 */ /********* Start of file library/asn1write.c ************/ /* * ASN.1 buffer writing functionality * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_ASN1_WRITE_C) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #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( *p - start < 3 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); // We assume we never have lengths larger than 65535 bytes // *--(*p) = len % 256; *--(*p) = ( len / 256 ) % 256; *--(*p) = 0x82; return( 3 ); } 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; // TODO negative values and values larger than 128 // DER format assumes 2s complement for numbers, so the leftmost bit // should be 0 for positive numbers and 1 for negative numbers. // 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_printable_string( unsigned char **p, unsigned char *start, 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, MBEDTLS_ASN1_PRINTABLE_STRING ) ); return( (int) len ); } int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, 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, MBEDTLS_ASN1_IA5_STRING ) ); return( (int) 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; size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); // Calculate byte length // if( *p < start || (size_t)( *p - start ) < size + 1 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); len = size + 1; (*p) -= size; memcpy( *p, buf, size ); // Write unused bits // *--(*p) = (unsigned char) (size * 8 - 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 ); } 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 = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) { // Add new entry if not present yet based on OID // if( ( cur = mbedtls_calloc( 1, sizeof(mbedtls_asn1_named_data) ) ) == 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 */ /********* Start of file library/base64.c ************/ /* * RFC 1521 base64 encoding/decoding * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_BASE64_C) #if !VXWORKS #include #endif #if defined(MBEDTLS_SELF_TEST) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #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 ) { *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 ); } n = ( ( n * 6 ) + 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 */ /********* Start of file library/bignum.c ************/ /* * Multi-precision integer library * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_BIGNUM_C) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #include #define mbedtls_printf printf #define mbedtls_calloc calloc #define mbedtls_free free #endif /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #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 ) ) /* * Initialize one MPI */ void mbedtls_mpi_init( mbedtls_mpi *X ) { if( X == NULL ) return; 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_zeroize( X->p, X->n * ciL ); 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; if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); if( X->n < nblimbs ) { if( ( p = mbedtls_calloc( nblimbs, ciL ) ) == NULL ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); if( X->p != NULL ) { memcpy( p, X->p, X->n * ciL ); mbedtls_zeroize( X->p, X->n * ciL ); 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; /* Actually resize up in this case */ if( X->n <= nblimbs ) return( mbedtls_mpi_grow( X, nblimbs ) ); for( i = X->n - 1; i > 0; i-- ) if( X->p[i] != 0 ) break; i++; if( i < nblimbs ) i = nblimbs; if( ( p = mbedtls_calloc( i, ciL ) ) == NULL ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); if( X->p != NULL ) { memcpy( p, X->p, i * ciL ); mbedtls_zeroize( X->p, X->n * ciL ); 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; size_t i; if( X == Y ) return( 0 ); if( Y->p == NULL ) { 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; MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); memset( X->p, 0, X->n * 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; 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; /* 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; 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; 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 ) { if( X->n * biL <= pos ) return( 0 ); return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); } /* * 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; 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; 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; 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 ) { int ret; mbedtls_mpi_uint r; if( radix < 2 || radix > 16 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); if( r < 10 ) *(*p)++ = (char)( r + 0x30 ); else *(*p)++ = (char)( r + 0x37 ); 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; if( radix < 2 || radix > 16 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); n = mbedtls_mpi_bitlen( X ); if( radix >= 4 ) n >>= 1; if( radix >= 16 ) n >>= 1; n += 3; if( buflen < n ) { *olen = n; return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); } p = buf; mbedtls_mpi_init( &T ); if( X->s == -1 ) *p++ = '-'; 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 ) ); } *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 ]; 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( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } if( 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 ]; 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 */ /* * 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 i, j, n; for( n = 0; n < buflen; n++ ) if( buf[n] != 0 ) break; MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); for( i = buflen, j = 0; i > n; i--, j++ ) X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); 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 i, j, n; n = mbedtls_mpi_size( X ); if( buflen < n ) return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); memset( buf, 0, buflen ); for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); 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; 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; 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; 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; 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 ); } /* * Compare signed values */ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) { mbedtls_mpi Y; mbedtls_mpi_uint p[1]; *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; 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; for( i = 0; i < j; i++, o++, p++ ) { *p += c; c = ( *p < c ); *p += *o; c += ( *p < *o ); } 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; i++; 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; 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 = 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 = 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]; 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]; 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; 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( i++; j > 0; j-- ) mpi_mul_hlp( i - 1, 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]; _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; 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]; 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; 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; 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 void 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; 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 ); } /* * Montgomery reduction: A = A * R^-1 mod N */ static void 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; 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; 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( wsize > MBEDTLS_MPI_WINDOW_SIZE ) wsize = MBEDTLS_MPI_WINDOW_SIZE; 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 ) ); 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 ) ); 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++ ) 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] ) ); 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 */ 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++ ) mpi_montmul( X, X, N, mm, &T ); /* * X = X * W[wbits] R^-1 mod N */ mpi_montmul( X, &W[wbits], N, mm, &T ); state--; nbits = 0; wbits = 0; } } /* * process the remaining bits */ for( i = 0; i < nbits; i++ ) { mpi_montmul( X, X, N, mm, &T ); wbits <<= 1; if( ( wbits & ( one << wsize ) ) != 0 ) mpi_montmul( X, &W[1], N, mm, &T ); } /* * X = A^E * R * R^-1 mod N = A^E mod N */ mpi_montred( X, N, mm, &T ); if( neg ) { 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; 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; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; if( size > MBEDTLS_MPI_MAX_SIZE ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); 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; if( mbedtls_mpi_cmp_int( N, 0 ) <= 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, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, count; size_t i, j, k, n, s; mbedtls_mpi W, R, T, A, RR; 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 ) ); i = mbedtls_mpi_bitlen( X ); /* * HAC, table 4.4 */ n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); for( i = 0; i < n; i++ ) { /* * pick a random A, 1 < A < |X| - 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) { j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); } A.p[0] |= 3; 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) { MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); } if (count++ > 30) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } } 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( const mbedtls_mpi *X, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; mbedtls_mpi XX; 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, f_rng, p_rng ) ); } /* * Prime number generation */ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; size_t k, n; mbedtls_mpi_uint r; mbedtls_mpi Y; if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); mbedtls_mpi_init( &Y ); n = BITS_TO_LIMBS( nbits ); MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); k = mbedtls_mpi_bitlen( X ); if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); mbedtls_mpi_set_bit( X, nbits-1, 1 ); X->p[0] |= 1; if( dh_flag == 0 ) { while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) { if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) goto cleanup; MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); } } 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, f_rng, p_rng ) ) == 0 && ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) { break; } 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 */ /********* Start of file library/blowfish.c ************/ /* * Blowfish implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_BLOWFISH_C) #include #if !defined(MBEDTLS_BLOWFISH_ALT) /* Implementation that should never be optimized out by the compiler */ static void blowfish_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 ) { memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); } void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) { if( ctx == NULL ) return; blowfish_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; if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || ( keybits % 8 ) ) { return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); } 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; 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]; 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 = *iv_off; 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 = *nc_off; 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 */ /********* Start of file library/camellia.c ************/ /* * Camellia implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_CAMELLIA_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #define FSb CAMELLIAFSb #if !defined(MBEDTLS_CAMELLIA_ALT) /* Implementation that should never be optimized out by the compiler */ static void camellia_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 ) { memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); } void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) { if( ctx == NULL ) return; camellia_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]; 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_INVALID_KEY_LENGTH ); } 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; 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]; ( (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]; 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 = *iv_off; 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 = *nc_off; 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 */ /* Amalgamated Release Mappings */ #undef FSb #endif /* MBEDTLS_CAMELLIA_C */ /********* Start of file library/ccm.c ************/ /* * NIST SP800-38C compliant CCM implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_CCM_C) #include #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ /* Implementation that should never be optimized out by the compiler */ static void ccm_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #define CCM_ENCRYPT 0 #define CCM_DECRYPT 1 /* * Initialize context */ void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) { 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; 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 ) { mbedtls_cipher_free( &ctx->cipher_ctx ); ccm_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 ) \ 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]; /* * 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) */ if( tag_len < 4 || 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_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 ) { return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len ) ); } /* * Authenticated decryption */ 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 ) { int ret; unsigned char check_tag[16]; unsigned char i; int diff; 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 ) { ccm_zeroize( output, length ); return( MBEDTLS_ERR_CCM_AUTH_FAILED ); } return( 0 ); } #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /* * Examples 1 to 3 from SP800-38C Appendix C */ #define NB_TESTS 3 /* * 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[] = { 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][32] = { { 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; unsigned char out[32]; 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 ); ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], iv, iv_len[i], ad, add_len[i], msg, out, out + msg_len[i], tag_len[i] ); if( ret != 0 || memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], iv, iv_len[i], ad, add_len[i], res[i], out, res[i] + msg_len[i], tag_len[i] ); if( ret != 0 || memcmp( out, 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 */ /********* Start of file library/certs.c ************/ /* * X.509 test certificates * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_CERTS_C) #if defined(MBEDTLS_ECDSA_C) #define TEST_CA_CRT_EC \ "-----BEGIN CERTIFICATE-----\r\n" \ "MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ "Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ "QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ "Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ "QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ "ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ "aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ "JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ "NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ "AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ "CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ "t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ "uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ "-----END CERTIFICATE-----\r\n" const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; const char mbedtls_test_ca_key_ec[] = "-----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"; const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; const char mbedtls_test_srv_crt_ec[] = "-----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"; const char mbedtls_test_srv_key_ec[] = "-----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"; const char mbedtls_test_cli_crt_ec[] = "-----BEGIN CERTIFICATE-----\r\n" "MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" "A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" "MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" "A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" "WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" "9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" "MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" "IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" "MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" "CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" "lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" "LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" "-----END CERTIFICATE-----\r\n"; const char mbedtls_test_cli_key_ec[] = "-----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"; const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); 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_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); #else #define TEST_CA_CRT_EC #endif /* MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_RSA_C) #define TEST_CA_CRT_RSA \ "-----BEGIN CERTIFICATE-----\r\n" \ "MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ "MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ "MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ "A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\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" \ "gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ "/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ "BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ "dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ "SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ "DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ "pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ "m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ "7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ "-----END CERTIFICATE-----\r\n" const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; const char mbedtls_test_ca_key_rsa[] = "-----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"; const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; const char mbedtls_test_srv_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" "MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" "MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" "A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\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/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" "oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" "UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" "iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" "wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" "RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" "zhuYwjVuX6JHG0c=\r\n" "-----END CERTIFICATE-----\r\n"; const char mbedtls_test_srv_key_rsa[] = "-----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"; const char mbedtls_test_cli_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" "MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" "MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" "A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\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/zANBgkqhkiG9w0BAQUFAAOC\r\n" "AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n" "LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n" "Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n" "8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n" "xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n" "D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n" "-----END CERTIFICATE-----\r\n"; const char mbedtls_test_cli_key_rsa[] = "-----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"; const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); 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_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); #else #define TEST_CA_CRT_RSA #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PEM_PARSE_C) /* Concatenation of all available CA certificates */ const char mbedtls_test_cas_pem[] = TEST_CA_CRT_RSA TEST_CA_CRT_EC; const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); #endif /* List of all available CA certificates */ const char * mbedtls_test_cas[] = { #if defined(MBEDTLS_RSA_C) mbedtls_test_ca_crt_rsa, #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) sizeof( mbedtls_test_ca_crt_rsa ), #endif #if defined(MBEDTLS_ECDSA_C) sizeof( mbedtls_test_ca_crt_ec ), #endif 0 }; #if defined(MBEDTLS_RSA_C) const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; const char *mbedtls_test_srv_key = mbedtls_test_srv_key_rsa; const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_rsa; const char *mbedtls_test_cli_key = mbedtls_test_cli_key_rsa; const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_rsa ); const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_rsa ); const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_rsa ); const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_rsa ); const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_rsa ); const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_rsa ); #else /* ! MBEDTLS_RSA_C, so MBEDTLS_ECDSA_C */ const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_ec; const char *mbedtls_test_ca_key = mbedtls_test_ca_key_ec; const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_ec; const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_ec; const char *mbedtls_test_srv_key = mbedtls_test_srv_key_ec; const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_ec; const char *mbedtls_test_cli_key = mbedtls_test_cli_key_ec; const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_ec ); const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_ec ); const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_ec ); const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_ec ); const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_ec ); const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_ec ); #endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_CERTS_C */ /********* Start of file library/cipher.c ************/ /** * \file cipher.c * * \brief Generic cipher wrapper for mbed TLS * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_CIPHER_C) #include #include #if defined(MBEDTLS_GCM_C) #endif #if defined(MBEDTLS_CCM_C) #endif #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) #define MBEDTLS_CIPHER_MODE_STREAM #endif /* Implementation that should never be optimized out by the compiler */ static void cipher_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* Amalgamated Release Mappings */ #define supported_init cipher_supported_init 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 ) { memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); } void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) { if( ctx == NULL ) return; if( ctx->cipher_ctx ) ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); cipher_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); } int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) { if( NULL == cipher_info || NULL == ctx ) 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 ) { if( NULL == ctx || NULL == ctx->cipher_info ) 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 CFB and CTR mode always use the encryption key schedule */ if( MBEDTLS_ENCRYPT == operation || MBEDTLS_MODE_CFB == 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; if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) 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 ); } memcpy( ctx->iv, iv, actual_iv_size ); ctx->iv_size = actual_iv_size; return( 0 ); } int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) { if( NULL == ctx || NULL == ctx->cipher_info ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); ctx->unprocessed_len = 0; return( 0 ); } #if defined(MBEDTLS_GCM_C) int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ) { if( NULL == ctx || NULL == ctx->cipher_info ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 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 ); } return( 0 ); } #endif /* MBEDTLS_GCM_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; if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } *olen = 0; if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) { if( ilen != mbedtls_cipher_get_block_size( ctx ) ) 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( input == output && ( ctx->unprocessed_len != 0 || ilen % mbedtls_cipher_get_block_size( ctx ) ) ) { 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 && ilen + ctx->unprocessed_len <= mbedtls_cipher_get_block_size( ctx ) ) || ( ctx->operation == MBEDTLS_ENCRYPT && ilen + ctx->unprocessed_len < mbedtls_cipher_get_block_size( ctx ) ) ) { memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, ilen ); ctx->unprocessed_len += ilen; return( 0 ); } /* * Process cached data first */ if( ctx->unprocessed_len != 0 ) { copy_len = mbedtls_cipher_get_block_size( ctx ) - 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, mbedtls_cipher_get_block_size( ctx ), ctx->iv, ctx->unprocessed_data, output ) ) ) { return( ret ); } *olen += mbedtls_cipher_get_block_size( ctx ); output += mbedtls_cipher_get_block_size( ctx ); ctx->unprocessed_len = 0; input += copy_len; ilen -= copy_len; } /* * Cache final, incomplete block */ if( 0 != ilen ) { copy_len = ilen % mbedtls_cipher_get_block_size( ctx ); if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) copy_len = mbedtls_cipher_get_block_size( ctx ); 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_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_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 = 0xFF; *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] ^ 0x80 ) | ( 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 ) { if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); *olen = 0; if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode || MBEDTLS_MODE_GCM == ctx->cipher_info->mode || MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) { 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 ) { if( NULL == ctx || 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) int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ) { if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); if( MBEDTLS_ENCRYPT != ctx->operation ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); return( 0 ); } int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ) { int ret; if( NULL == ctx || NULL == ctx->cipher_info || MBEDTLS_DECRYPT != ctx->operation ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { unsigned char check_tag[16]; size_t i; int diff; 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" */ for( diff = 0, i = 0; i < tag_len; i++ ) diff |= tag[i] ^ check_tag[i]; if( diff != 0 ) return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); return( 0 ); } return( 0 ); } #endif /* MBEDTLS_GCM_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; 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 ) { #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 */ 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 ) { #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 */ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } #endif /* MBEDTLS_CIPHER_MODE_AEAD */ /* Amalgamated Release Mappings */ #undef supported_init #endif /* MBEDTLS_CIPHER_C */ /********* Start of file library/cipher_wrap.c ************/ /** * \file cipher_wrap.c * * \brief Generic cipher wrapper for mbed TLS * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_CIPHER_C) #if defined(MBEDTLS_AES_C) #endif #if defined(MBEDTLS_ARC4_C) #endif #if defined(MBEDTLS_CAMELLIA_C) #endif #if defined(MBEDTLS_DES_C) #endif #if defined(MBEDTLS_BLOWFISH_C) #endif #if defined(MBEDTLS_GCM_C) #endif #if defined(MBEDTLS_CCM_C) #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #include #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #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_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 */ 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_CTR) aes_crypt_ctr_wrap, #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", 16, 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", 16, 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", 16, 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_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_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_CTR) 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_CTR) 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_CTR) camellia_crypt_ctr_wrap, #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_CTR) 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_CTR) 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_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_CTR) 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_CTR) 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_CTR) 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_CTR) blowfish_crypt_ctr_wrap, #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_CTR) 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_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_CTR) 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_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_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_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_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 */ /********* Start of file library/ctr_drbg.c ************/ /* * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The NIST SP 800-90 DRBGs are described in the following publucation. * * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_CTR_DRBG_C) #include #if defined(MBEDTLS_FS_IO) #include #endif #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ /* Implementation that should never be optimized out by the compiler */ static void ctr_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 } /* * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST * tests to succeed (which require known length fixed entropy) */ 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 ) { 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; ctx->entropy_len = entropy_len; ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; /* * Initialize with an empty key */ mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) return( ret ); return( 0 ); } 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 ) { return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); } 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 ); ctr_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 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; mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); /* * 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; mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ); } memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); /* * Update IV */ buf[3]++; } /* * Do final encryption with reduced data */ mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; p = output; for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) { mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } mbedtls_aes_free( &aes_ctx ); return( 0 ); } 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; 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 */ mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) tmp[i] ^= data[i]; /* * Update key and counter */ mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); return( 0 ); } void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len ) { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; if( add_len > 0 ) { /* 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; block_cipher_df( add_input, additional, add_len ); ctr_drbg_update_internal( ctx, add_input ); } } 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; if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 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 */ block_cipher_df( seed, seed, seedlen ); /* * Update state */ ctr_drbg_update_internal( ctx, seed ); ctx->reseed_counter = 1; return( 0 ); } 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 ) { block_cipher_df( add_input, additional, add_len ); ctr_drbg_update_internal( ctx, add_input ); } 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 */ mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ); 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; } ctr_drbg_update_internal( ctx, add_input ); ctx->reseed_counter++; return( 0 ); } 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; goto exit; } ret = 0; exit: fclose( f ); return( ret ); } int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) { FILE *f; size_t n; unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); fseek( f, 0, SEEK_END ); n = (size_t) ftell( f ); fseek( f, 0, SEEK_SET ); if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) { fclose( f ); return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); } if( fread( buf, 1, n, f ) != n ) { fclose( f ); return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); } fclose( f ); mbedtls_ctr_drbg_update( ctx, buf, n ); 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; CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); 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; CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); 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 */ /********* Start of file library/debug.c ************/ /* * Debugging routines * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_DEBUG_C) #include #include #include #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #define mbedtls_snprintf snprintf #endif #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", 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( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) return; va_start( argp, format ); #if defined(_WIN32) #if defined(_TRUNCATE) 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( ssl->conf == NULL || ssl->conf->f_dbg == NULL || 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( ssl->conf == NULL || ssl->conf->f_dbg == NULL || 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( ssl->conf == NULL || ssl->conf->f_dbg == NULL || 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( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || 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( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || 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 */ #endif /* MBEDTLS_DEBUG_C */ /********* Start of file library/des.c ************/ /* * FIPS-46-3 compliant Triple-DES implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_DES_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_DES_ALT) /* Implementation that should never be optimized out by the compiler */ static void des_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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) \ { \ 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; \ } /* * Final Permutation macro */ #define DES_FP(X,Y) \ { \ 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); \ } /* * DES round macro */ #define DES_ROUND(X,Y) \ { \ 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 ]; \ } #define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 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; des_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; des_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 ); des_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 ); des_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 ); des_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 ); des_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 */ /********* Start of file library/dhm.c ************/ /* * Diffie-Hellman-Merkle key exchange * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ /* * Reference: * * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_DHM_C) #include #if defined(MBEDTLS_PEM_PARSE_C) #endif #if defined(MBEDTLS_ASN1_PARSE_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #include #define mbedtls_printf printf #define mbedtls_calloc calloc #define mbedtls_free free #endif /* Implementation that should never be optimized out by the compiler */ static void dhm_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 * * 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 = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; 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 = 0; } cleanup: mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); return( ret ); } void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) { 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; 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; 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_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) \ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, p + 2, n ) ); \ *p++ = (unsigned char)( n >> 8 ); \ *p++ = (unsigned char)( n ); p += n; 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 ); } /* * 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; if( ctx == NULL || 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; if( ctx == NULL || 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_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_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; if( ctx == NULL || 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 ) { 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 ); dhm_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; 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_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; if( ( ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); dhm_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); } #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_SELF_TEST) 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"; 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 */ /********* Start of file library/ecdh.c ************/ /* * Elliptic curve Diffie-Hellman * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_ECDH_C) #include /* * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair */ 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 ) { return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); } /* * 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 ) { int ret; mbedtls_ecp_point P; mbedtls_ecp_point_init( &P ); /* * Make sure Q is a valid pubkey before using it */ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); 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 ); } /* * Initialize context */ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); } /* * Free context */ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) { if( ctx == NULL ) return; mbedtls_ecp_group_free( &ctx->grp ); mbedtls_ecp_point_free( &ctx->Q ); mbedtls_ecp_point_free( &ctx->Qp ); mbedtls_ecp_point_free( &ctx->Vi ); mbedtls_ecp_point_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->d ); mbedtls_mpi_free( &ctx->z ); mbedtls_mpi_free( &ctx->_d ); } /* * 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 ret; size_t grp_len, pt_len; if( ctx == NULL || ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) != 0 ) return( ret ); 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, ctx->point_format, &pt_len, buf, blen ) ) != 0 ) return( ret ); *olen = grp_len + pt_len; return( 0 ); } /* * 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; if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) return( ret ); if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) != 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; if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) return( 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 ); } /* * 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 ret; if( ctx == NULL || ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) != 0 ) return( ret ); return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, olen, buf, blen ); } /* * Parse and import the client's public value */ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, const unsigned char *buf, size_t blen ) { int ret; const unsigned char *p = buf; if( ctx == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 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 ); } /* * 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 ret; if( ctx == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng ) ) != 0 ) { return( ret ); } 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 ); } #endif /* MBEDTLS_ECDH_C */ /********* Start of file library/ecdsa.c ************/ /* * Elliptic curve DSA * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_ECDSA_C) #include #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #endif /* * 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 ); } /* * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash 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 ) { int ret, key_tries, sign_tries, blind_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; /* 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 ); mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); sign_tries = 0; do { /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ key_tries = 0; do { MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); if( key_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } } while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); /* * 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. */ blind_tries = 0; do { size_t n_size = ( grp->nbits + 7 ) / 8; MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); /* See mbedtls_ecp_gen_keypair() */ if( ++blind_tries > 30 ) return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); } while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, 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( &k, &k, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); if( sign_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } } while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); return( ret ); } #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Deterministic signature wrapper */ 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 ) { int ret; mbedtls_hmac_drbg_context 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 ); /* 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( &rng_ctx, md_info, data, 2 * grp_len ); ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, &rng_ctx ); cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_mpi_free( &h ); return( ret ); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /* * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash 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) { int ret; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; 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 ); /* * 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; } /* * Additional precaution: make sure Q is valid */ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); /* * 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 */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); /* * Step 5: R = u1 G + u2 Q * * Since we're not using any secret data, no need to pass a RNG to * mbedtls_ecp_mul() for countermesures. */ MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); 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 ); return( ret ); } /* * 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( 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 ) { int ret; mbedtls_mpi r, s; mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) (void) f_rng; (void) p_rng; MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, hash, hlen, md_alg ) ); #else (void) md_alg; MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng ) ); #endif MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); } #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 ) { 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 ) { int ret; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; 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( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; if( p != end ) ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); } /* * 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 ) { return( mbedtls_ecp_group_load( &ctx->grp, gid ) || mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); } /* * Set context from an mbedtls_ecp_keypair */ int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) { int ret; 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 ) { mbedtls_ecp_keypair_init( ctx ); } /* * Free context */ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) { mbedtls_ecp_keypair_free( ctx ); } #endif /* MBEDTLS_ECDSA_C */ /********* Start of file library/ecjpake.c ************/ /* * Elliptic curve J-PAKE * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_ECJPAKE_C) #include /* * 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 ) { if( ctx == NULL ) return; 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; 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 ) { 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_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 ) { 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 ) { 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 */ 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; 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; *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 #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #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 correponding 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 */ /********* Start of file library/ecp.c ************/ /* * Elliptic curves over GF(p): generic functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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 * * [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. * * * [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. * */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_ECP_C) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #include #define mbedtls_printf printf #define mbedtls_calloc calloc #define mbedtls_free free #endif #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline #endif /* Implementation that should never be optimized out by the compiler */ static void ecp_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #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_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) #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; 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 ) { if( pt == NULL ) return; 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 ) { if( grp == NULL ) return; memset( grp, 0, sizeof( mbedtls_ecp_group ) ); } /* * Initialize (the components of) a key pair */ void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) { if( key == NULL ) return; 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 ); } ecp_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; 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 ) { return mbedtls_ecp_group_load( dst, src->id ); } /* * Set point to zero */ int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) { int ret; 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 ) { return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); } /* * Compare two points lazyly */ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) { 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; 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; if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && format != MBEDTLS_ECP_PF_COMPRESSED ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); /* * 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; 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; /* * 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; /* * 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 ) { uint16_t tls_id; const mbedtls_ecp_curve_info *curve_info; /* * 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 ); return mbedtls_ecp_group_load( grp, curve_info->grp_id ); } /* * 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; 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 ); 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_len ) { int ret; size_t i; mbedtls_mpi *c, u, Zi, ZZi; if( t_len < 2 ) return( ecp_normalize_jac( grp, *T ) ); if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); 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_len; 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_len-1], &grp->P ) ); for( i = t_len - 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_len; 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 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 /* * 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 = ( grp->pbits + 7 ) / 8; int count = 0; mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); /* Generate l such that 1 < l < p */ do { 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. * * Also, for the sake of compactness, only the seven low-order bits of x[i] * are used to represent K_i, and the msb of x[i] encodes the 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_fixed( 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 comb method * * If i = i_{w-1} ... i_1 is the binary representation of i, then * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P * * T must be able to hold 2^{w - 1} elements * * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) */ 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 ) { int ret; unsigned char i, k; size_t j; mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; /* * 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 ) ); k = 0; for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) { cur = T + i; MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); for( j = 0; j < d; j++ ) MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); TT[k++] = cur; } MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ k = 0; for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) { j = i; while( j-- ) { MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); TT[k++] = &T[i + j]; } } MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); cleanup: return( ret ); } /* * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] */ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point T[], unsigned char t_len, 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_len; 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_len, const unsigned char x[], size_t d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; mbedtls_ecp_point Txi; size_t i; mbedtls_ecp_point_init( &Txi ); /* Start with a non-zero point and randomize its coordinates */ i = d; MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, 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_MPI_CHK( ecp_double_jac( grp, R, R ) ); MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); } cleanup: mbedtls_ecp_point_free( &Txi ); return( ret ); } /* * Multiplication using the comb method, * for curves in short Weierstrass form */ 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 ) { int ret; unsigned char w, m_is_odd, p_eq_g, pre_len, i; size_t d; unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *T; mbedtls_mpi M, mm; mbedtls_mpi_init( &M ); mbedtls_mpi_init( &mm ); /* we need N to be odd to trnaform m in an odd number, check now */ if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); /* * 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 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 ); if( p_eq_g ) w++; #else p_eq_g = 0; #endif /* * 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; /* Other sizes that depend on w */ pre_len = 1U << ( w - 1 ); d = ( grp->nbits + w - 1 ) / w; /* * Prepare precomputed points: if P == G we want to * use grp->T if already initialized, or initialize it. */ T = p_eq_g ? grp->T : NULL; if( T == NULL ) { T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); if( T == NULL ) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); if( p_eq_g ) { grp->T = T; grp->T_size = pre_len; } } /* * Make sure M is odd (M = m or M = N - m, since N is odd) * using the fact that m * P = - (N - m) * P */ m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); 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, ! m_is_odd ) ); /* * Go for comb multiplication, R = M * P */ ecp_comb_fixed( k, d, w, &M ); MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); /* * Now get m * P from M * P and normalize it */ MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); cleanup: if( T != NULL && ! p_eq_g ) { for( i = 0; i < pre_len; i++ ) mbedtls_ecp_point_free( &T[i] ); mbedtls_free( T ); } mbedtls_mpi_free( &M ); mbedtls_mpi_free( &mm ); if( ret != 0 ) mbedtls_ecp_point_free( R ); 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; 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 = ( grp->pbits + 7 ) / 8; int count = 0; mbedtls_mpi_init( &l ); /* Generate l such that 1 < l < p */ do { 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; 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 ) ); } MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); cleanup: mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); return( ret ); } #endif /* ECP_MONTGOMERY */ /* * 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 ) { int ret; /* Common sanity checks */ if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) return( ret ); #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) return( 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 ) return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng ) ); #endif return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); } #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 ) { 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( grp, R, m, P, NULL, NULL ) ); } cleanup: 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 ) { int ret; mbedtls_ecp_point mP; if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); mbedtls_ecp_point_init( &mP ); MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); cleanup: mbedtls_ecp_point_free( &mP ); return( ret ); } #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 */ 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 ) { /* 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 ) { #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) { /* see [Curve25519] page 5 */ if( mbedtls_mpi_get_bit( d, 0 ) != 0 || mbedtls_mpi_get_bit( d, 1 ) != 0 || mbedtls_mpi_get_bit( d, 2 ) != 0 || mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ return( MBEDTLS_ERR_ECP_INVALID_KEY ); else 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 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; size_t n_size = ( grp->nbits + 7 ) / 8; #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) { /* [M225] page 5 */ size_t b; MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); /* 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 three bits are unset */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); } else #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 char rnd[MBEDTLS_ECP_MAX_BYTES]; /* * 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( f_rng( p_rng, rnd, n_size ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) ); 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 ); } while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); } else #endif /* ECP_SHORTWEIERSTRASS */ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); cleanup: if( ret != 0 ) return( ret ); return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); } /* * 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 ) { 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; 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; 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_C */ /********* Start of file library/ecp_curves.c ************/ /* * Elliptic curves over GF(p): curve-specific data and functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_ECP_C) #include #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline #endif /* Amalgamated Release Mappings */ #undef ADD /* * 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_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 ); /* Y intentionaly 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 */ /* * Set a group using well-known domain parameters */ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) { 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 */ 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 ) M.n = P255_WIDTH + 1; 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_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]; 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 - adjust; /* 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 - adjust; /* 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 */ /* Amalgamated Release Mappings */ #undef ADD #endif /* MBEDTLS_ECP_C */ /********* Start of file library/entropy.c ************/ /* * Entropy accumulator implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_ENTROPY_C) #include #if defined(MBEDTLS_FS_IO) #include #endif #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if defined(MBEDTLS_HAVEGE_C) #endif /* Implementation that should never be optimized out by the compiler */ static void entropy_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) { memset( ctx, 0, sizeof(mbedtls_entropy_context) ); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init( &ctx->mutex ); #endif #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_starts( &ctx->accumulator, 0 ); #else mbedtls_sha256_starts( &ctx->accumulator, 0 ); #endif #if defined(MBEDTLS_HAVEGE_C) mbedtls_havege_init( &ctx->havege_data ); #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 #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 entropy_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); } 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 index, ret = 0; #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif index = ctx->source_count; if( index >= MBEDTLS_ENTROPY_MAX_SOURCES ) { ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; goto exit; } ctx->source[index].f_source = f_source; ctx->source[index].p_source = p_source; ctx->source[index].threshold = threshold; ctx->source[index].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; if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) { #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512( data, len, tmp, 0 ); #else mbedtls_sha256( data, len, tmp, 0 ); #endif p = tmp; use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; } header[0] = source_id; header[1] = use_len & 0xFF; #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_update( &ctx->accumulator, header, 2 ); mbedtls_sha512_update( &ctx->accumulator, p, use_len ); #else mbedtls_sha256_update( &ctx->accumulator, header, 2 ); mbedtls_sha256_update( &ctx->accumulator, p, use_len ); #endif return( 0 ); } 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 ) { return( ret ); } /* * Add if we actually gathered something */ if( olen > 0 ) { entropy_update( ctx, (unsigned char) i, buf, olen ); ctx->source[i].size += olen; } } if( have_one_strong == 0 ) return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); return( 0 ); } /* * 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_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 ) { 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) mbedtls_sha512_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); mbedtls_sha512_starts( &ctx->accumulator, 0 ); mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-512 on entropy */ mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ mbedtls_sha256_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); mbedtls_sha256_starts( &ctx->accumulator, 0 ); mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-256 on entropy */ mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); #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: #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_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: fclose( f ); return( ret ); } int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) { 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 ) { fclose( f ); return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); } fclose( f ); mbedtls_entropy_update_manual( ctx, buf, n ); return( mbedtls_entropy_write_seed_file( ctx, path ) ); } #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /* * 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 ); } /* * 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 = 0; mbedtls_entropy_context ctx; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; size_t i, j; if( verbose != 0 ) mbedtls_printf( " ENTROPY test: " ); 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; } } cleanup: mbedtls_entropy_free( &ctx ); 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 */ /********* Start of file library/entropy_poll.c ************/ /* * Platform-specific and custom entropy polling functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_ENTROPY_C) #if defined(MBEDTLS_TIMING_C) #include #endif #if defined(MBEDTLS_HAVEGE_C) #endif #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #if !defined(_WIN32_WINNT) #define _WIN32_WINNT 0x0400 #endif #include #include 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 ) 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 #include #if defined(SYS_getrandom) #define HAVE_GETRANDOM 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 ) ); } #include /* Check if version is at least 3.17.0 */ static int check_version_3_17_plus( void ) { int minor; struct utsname un; const char *ver; /* Get version information */ uname(&un); ver = un.release; /* Check major version; assume a single digit */ if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) return( -1 ); if( ver[0] - '0' > 3 ) return( 0 ); /* Ok, so now we know major == 3, check minor. * Assume 1 or 2 digits. */ if( ver[2] < '0' || ver[2] > '9' ) return( -1 ); minor = ver[2] - '0'; if( ver[3] >= '0' && ver[3] <= '9' ) minor = 10 * minor + ver[3] - '0'; else if( ver [3] != '.' ) return( -1 ); if( minor < 17 ) return( -1 ); return( 0 ); } static int has_getrandom = -1; #endif /* SYS_getrandom */ #endif /* __linux__ */ #include int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen ) { FILE *file; size_t read_len; ((void) data); #if defined(HAVE_GETRANDOM) if( has_getrandom == -1 ) has_getrandom = ( check_version_3_17_plus() == 0 ); if( has_getrandom ) { int ret; if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); *olen = ret; return( 0 ); } #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 */ #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 */ #endif /* MBEDTLS_ENTROPY_C */ /********* Start of file library/error.c ************/ /* * Error message information * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) #include #endif #if defined(MBEDTLS_PLATFORM_C) #else #define mbedtls_snprintf snprintf #endif #if defined(MBEDTLS_ERROR_C) #include #if defined(MBEDTLS_AES_C) #endif #if defined(MBEDTLS_BASE64_C) #endif #if defined(MBEDTLS_BIGNUM_C) #endif #if defined(MBEDTLS_BLOWFISH_C) #endif #if defined(MBEDTLS_CAMELLIA_C) #endif #if defined(MBEDTLS_CCM_C) #endif #if defined(MBEDTLS_CIPHER_C) #endif #if defined(MBEDTLS_CTR_DRBG_C) #endif #if defined(MBEDTLS_DES_C) #endif #if defined(MBEDTLS_DHM_C) #endif #if defined(MBEDTLS_ECP_C) #endif #if defined(MBEDTLS_ENTROPY_C) #endif #if defined(MBEDTLS_GCM_C) #endif #if defined(MBEDTLS_HMAC_DRBG_C) #endif #if defined(MBEDTLS_MD_C) #endif #if defined(MBEDTLS_NET_C) #endif #if defined(MBEDTLS_OID_C) #endif #if defined(MBEDTLS_PADLOCK_C) #endif #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #endif #if defined(MBEDTLS_PK_C) #endif #if defined(MBEDTLS_PKCS12_C) #endif #if defined(MBEDTLS_PKCS5_C) #endif #if defined(MBEDTLS_RSA_C) #endif #if defined(MBEDTLS_SSL_TLS_C) #endif #if defined(MBEDTLS_THREADING_C) #endif #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) #endif #if defined(MBEDTLS_XTEA_C) #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 to function" ); 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)" ); #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 to function" ); 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/write of file 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 - Requested curve not available" ); 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 - Signature is valid but shorter than the user-supplied length" ); #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" ); #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 signature is valid but its length is less than expected" ); #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 library's validity check" ); 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" ); #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 - Connection requires a read call" ); 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" ); #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" ); #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" ); #endif /* MBEDTLS_AES_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_INVALID_KEY_LENGTH) ) mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); #endif /* MBEDTLS_BLOWFISH_C */ #if defined(MBEDTLS_CAMELLIA_C) if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); #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 function" ); if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); #endif /* MBEDTLS_CCM_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 - Too many random requested in single call" ); if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) mbedtls_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read/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" ); #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_BAD_INPUT) ) mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); #endif /* MBEDTLS_GCM_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_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" ); #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_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" ); #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 */ /********* Start of file library/gcm.c ************/ /* * NIST SP800-38D compliant GCM implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_GCM_C) #include #if defined(MBEDTLS_AESNI_C) #endif #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ /* * 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 /* Implementation that should never be optimized out by the compiler */ static void gcm_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * Initialize a context */ void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) { 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; 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; /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ if( ( (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; 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 = ctx->len * 8; uint64_t orig_add_len = ctx->add_len * 8; if( tag_len > 16 || tag_len < 4 ) return( MBEDTLS_ERR_GCM_BAD_INPUT ); if( tag_len != 0 ) 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; 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; 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 ) { gcm_zeroize( output, length ); return( MBEDTLS_ERR_GCM_AUTH_FAILED ); } return( 0 ); } void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) { mbedtls_cipher_free( &ctx->cipher_ctx ); gcm_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); } #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; mbedtls_gcm_init( &ctx ); for( j = 0; j < 3; j++ ) { int key_len = 128 + 64 * j; for( i = 0; i < MAX_TESTS; i++ ) { if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "enc" ); mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 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 || memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } mbedtls_gcm_free( &ctx ); if( verbose != 0 ) mbedtls_printf( "passed\n" ); if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "dec" ); mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 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 || memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } mbedtls_gcm_free( &ctx ); if( verbose != 0 ) mbedtls_printf( "passed\n" ); if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", key_len, i, "enc" ); mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 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 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } 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 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, buf + 32 ); if( ret != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } } else { ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); if( ret != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } } ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); if( ret != 0 || memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } mbedtls_gcm_free( &ctx ); if( verbose != 0 ) mbedtls_printf( "passed\n" ); if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", key_len, i, "dec" ); mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 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 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } 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 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, buf + 32 ); if( ret != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } } else { ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); if( ret != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } } ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); if( ret != 0 || memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } mbedtls_gcm_free( &ctx ); if( verbose != 0 ) mbedtls_printf( "passed\n" ); } } if( verbose != 0 ) mbedtls_printf( "\n" ); return( 0 ); } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_GCM_C */ /********* Start of file library/havege.c ************/ /** * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_HAVEGE_C) #include /* Implementation that should never be optimized out by the compiler */ static void havege_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* ------------------------------------------------------------------------ * 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) { int *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 = (int) 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 = (int) 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++ ) \ hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; /* * Entropy gathering function */ static void havege_fill( mbedtls_havege_state *hs ) { int i, n = 0; int U1, U2, *A, *B, *C, *D; int PT1, PT2, *WALK, RES[16]; int PTX, PTY, CLK, PTEST, IN; WALK = hs->WALK; PT1 = hs->PT1; PT2 = hs->PT2; PTX = U1 = 0; PTY = U2 = 0; 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; havege_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 */ /********* Start of file library/hmac_drbg.c ************/ /* * HMAC_DRBG implementation (NIST SP 800-90) * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_HMAC_DRBG_C) #include #if defined(MBEDTLS_FS_IO) #include #endif #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_PLATFORM_C */ /* Implementation that should never be optimized out by the compiler */ static void hmac_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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) */ void mbedtls_hmac_drbg_update( 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]; for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) { /* Step 1 or 4 */ mbedtls_md_hmac_reset( &ctx->md_ctx ); mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); if( rounds == 2 ) mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); mbedtls_md_hmac_finish( &ctx->md_ctx, K ); /* Step 2 or 5 */ mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); } } /* * 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. */ mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); mbedtls_hmac_drbg_update( ctx, data, data_len ); return( 0 ); } /* * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) */ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len ) { unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; size_t seedlen; /* III. Check input length */ if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || ctx->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( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); seedlen = ctx->entropy_len; /* 1. Concatenate entropy and additional data if any */ if( additional != NULL && len != 0 ) { memcpy( seed + seedlen, additional, len ); seedlen += len; } /* 2. Update state */ mbedtls_hmac_drbg_update( ctx, seed, seedlen ); /* 3. Reset reseed_counter */ ctx->reseed_counter = 1; /* 4. Done */ return( 0 ); } /* * HMAC_DRBG initialisation (10.1.2.3 + 9.1) */ 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 entropy_len, 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. */ mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); memset( ctx->V, 0x01, md_size ); ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; /* * 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.) */ 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 */ /* * For initialisation, use more entropy to emulate a nonce * (Again, matches test vectors.) */ ctx->entropy_len = entropy_len * 3 / 2; if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) return( ret ); ctx->entropy_len = entropy_len; 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 reseeds */ 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 ) mbedtls_hmac_drbg_update( ctx, additional, add_len ); /* 3, 4, 5. Generate bytes */ while( left != 0 ) { size_t use_len = left > md_len ? md_len : left; mbedtls_md_hmac_reset( &ctx->md_ctx ); mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); memcpy( out, ctx->V, use_len ); out += use_len; left -= use_len; } /* 6. Update */ mbedtls_hmac_drbg_update( ctx, additional, add_len ); /* 7. Update reseed counter */ ctx->reseed_counter++; /* 8. Done */ return( 0 ); } /* * 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 ); hmac_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 ); return( ret ); } int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) { FILE *f; size_t n; unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); fseek( f, 0, SEEK_END ); n = (size_t) ftell( f ); fseek( f, 0, SEEK_SET ); if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) { fclose( f ); return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); } if( fread( buf, 1, n, f ) != n ) { fclose( f ); return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); } fclose( f ); mbedtls_hmac_drbg_update( ctx, buf, n ); 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 */ /********* Start of file library/md.c ************/ /** * \file mbedtls_md.c * * \brief Generic message digest wrapper for mbed TLS * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_MD_C) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #include #if defined(MBEDTLS_FS_IO) #include #endif /* Implementation that should never be optimized out by the compiler */ static void md_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 ) { md_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); mbedtls_free( ctx->hmac_ctx ); } md_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 ); ctx->md_info->starts_func( ctx->md_ctx ); return( 0 ); } 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 ); ctx->md_info->update_func( ctx->md_ctx, input, ilen ); return( 0 ); } 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 ); ctx->md_info->finish_func( ctx->md_ctx, output ); return( 0 ); } 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 ); md_info->digest_func( input, ilen, output ); return( 0 ); } #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; md_info->starts_func( ctx.md_ctx ); while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md_info->update_func( ctx.md_ctx, buf, n ); if( ferror( f ) != 0 ) { ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; goto cleanup; } md_info->finish_func( ctx.md_ctx, output ); cleanup: 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 ) { 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 ) { ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, key, keylen ); ctx->md_info->finish_func( ctx->md_ctx, sum ); 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] ); } md_zeroize( sum, sizeof( sum ) ); ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); return( 0 ); } 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 ); ctx->md_info->update_func( ctx->md_ctx, input, ilen ); return( 0 ); } int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) { 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; ctx->md_info->finish_func( ctx->md_ctx, tmp ); ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); ctx->md_info->finish_func( ctx->md_ctx, output ); return( 0 ); } int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) { 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; ctx->md_info->starts_func( ctx->md_ctx ); ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); return( 0 ); } 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 ) return( ret ); mbedtls_md_hmac_starts( &ctx, key, keylen ); mbedtls_md_hmac_update( &ctx, input, ilen ); mbedtls_md_hmac_finish( &ctx, output ); mbedtls_md_free( &ctx ); return( 0 ); } 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 ); ctx->md_info->process_func( ctx->md_ctx, data ); return( 0 ); } 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 */ /********* Start of file library/md2.c ************/ /* * RFC 1115/1319 compliant MD2 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_MD2_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_MD2_ALT) /* Implementation that should never be optimized out by the compiler */ static void md2_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } 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; md2_zeroize( ctx, sizeof( mbedtls_md2_context ) ); } void mbedtls_md2_clone( mbedtls_md2_context *dst, const mbedtls_md2_context *src ) { *dst = *src; } /* * MD2 context setup */ void mbedtls_md2_starts( mbedtls_md2_context *ctx ) { memset( ctx->cksum, 0, 16 ); memset( ctx->state, 0, 46 ); memset( ctx->buffer, 0, 16 ); ctx->left = 0; } #if !defined(MBEDTLS_MD2_PROCESS_ALT) void mbedtls_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]; } } #endif /* !MBEDTLS_MD2_PROCESS_ALT */ /* * MD2 process buffer */ void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; while( ilen > 0 ) { if( ctx->left + ilen > 16 ) 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; mbedtls_md2_process( ctx ); } } } /* * MD2 final digest */ void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) { size_t i; unsigned char x; x = (unsigned char)( 16 - ctx->left ); for( i = ctx->left; i < 16; i++ ) ctx->buffer[i] = x; mbedtls_md2_process( ctx ); memcpy( ctx->buffer, ctx->cksum, 16 ); mbedtls_md2_process( ctx ); memcpy( output, ctx->state, 16 ); } #endif /* !MBEDTLS_MD2_ALT */ /* * output = MD2( input buffer ) */ void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) { mbedtls_md2_context ctx; mbedtls_md2_init( &ctx ); mbedtls_md2_starts( &ctx ); mbedtls_md2_update( &ctx, input, ilen ); mbedtls_md2_finish( &ctx, output ); mbedtls_md2_free( &ctx ); } #if defined(MBEDTLS_SELF_TEST) /* * RFC 1319 test vectors */ static const char md2_test_str[7][81] = { { "" }, { "a" }, { "abc" }, { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "12345678901234567890123456789012345678901234567890123456789012" \ "345678901234567890" } }; 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; unsigned char md2sum[16]; for( i = 0; i < 7; i++ ) { if( verbose != 0 ) mbedtls_printf( " MD2 test #%d: ", i + 1 ); mbedtls_md2( (unsigned char *) md2_test_str[i], strlen( md2_test_str[i] ), md2sum ); if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } if( verbose != 0 ) mbedtls_printf( "passed\n" ); } if( verbose != 0 ) mbedtls_printf( "\n" ); return( 0 ); } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_MD2_C */ /********* Start of file library/md4.c ************/ /* * RFC 1186/1320 compliant MD4 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_MD4_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_MD4_ALT) /* Implementation that should never be optimized out by the compiler */ static void md4_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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; md4_zeroize( ctx, sizeof( mbedtls_md4_context ) ); } void mbedtls_md4_clone( mbedtls_md4_context *dst, const mbedtls_md4_context *src ) { *dst = *src; } /* * MD4 context setup */ void mbedtls_md4_starts( 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; } #if !defined(MBEDTLS_MD4_PROCESS_ALT) void mbedtls_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) { a += F(b,c,d) + x; a = S(a,s); } 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) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } 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) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } 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; } #endif /* !MBEDTLS_MD4_PROCESS_ALT */ /* * MD4 process buffer */ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; uint32_t left; if( ilen == 0 ) return; 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 ); mbedtls_md4_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { mbedtls_md4_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), (void *) input, ilen ); } } 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 */ void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) { 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 ); mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn ); mbedtls_md4_update( ctx, msglen, 8 ); 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 ); } #endif /* !MBEDTLS_MD4_ALT */ /* * output = MD4( input buffer ) */ void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) { mbedtls_md4_context ctx; mbedtls_md4_init( &ctx ); mbedtls_md4_starts( &ctx ); mbedtls_md4_update( &ctx, input, ilen ); mbedtls_md4_finish( &ctx, output ); mbedtls_md4_free( &ctx ); } #if defined(MBEDTLS_SELF_TEST) /* * RFC 1320 test vectors */ static const char md4_test_str[7][81] = { { "" }, { "a" }, { "abc" }, { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "12345678901234567890123456789012345678901234567890123456789012" \ "345678901234567890" } }; 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; unsigned char md4sum[16]; for( i = 0; i < 7; i++ ) { if( verbose != 0 ) mbedtls_printf( " MD4 test #%d: ", i + 1 ); mbedtls_md4( (unsigned char *) md4_test_str[i], strlen( md4_test_str[i] ), md4sum ); if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } if( verbose != 0 ) mbedtls_printf( "passed\n" ); } if( verbose != 0 ) mbedtls_printf( "\n" ); return( 0 ); } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_MD4_C */ /********* Start of file library/md5.c ************/ /* * RFC 1321 compliant MD5 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_MD5_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_MD5_ALT) /* Implementation that should never be optimized out by the compiler */ static void md5_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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; md5_zeroize( ctx, sizeof( mbedtls_md5_context ) ); } void mbedtls_md5_clone( mbedtls_md5_context *dst, const mbedtls_md5_context *src ) { *dst = *src; } /* * MD5 context setup */ void mbedtls_md5_starts( 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; } #if !defined(MBEDTLS_MD5_PROCESS_ALT) void mbedtls_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) \ { \ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ } 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; } #endif /* !MBEDTLS_MD5_PROCESS_ALT */ /* * MD5 process buffer */ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; uint32_t left; if( ilen == 0 ) return; 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 ); mbedtls_md5_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { mbedtls_md5_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), input, ilen ); } } static const unsigned char md5_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 }; /* * MD5 final digest */ void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) { 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 ); mbedtls_md5_update( ctx, md5_padding, padn ); mbedtls_md5_update( ctx, msglen, 8 ); 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 ); } #endif /* !MBEDTLS_MD5_ALT */ /* * output = MD5( input buffer ) */ void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) { mbedtls_md5_context ctx; mbedtls_md5_init( &ctx ); mbedtls_md5_starts( &ctx ); mbedtls_md5_update( &ctx, input, ilen ); mbedtls_md5_finish( &ctx, output ); mbedtls_md5_free( &ctx ); } #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 int 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; unsigned char md5sum[16]; for( i = 0; i < 7; i++ ) { if( verbose != 0 ) mbedtls_printf( " MD5 test #%d: ", i + 1 ); mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } if( verbose != 0 ) mbedtls_printf( "passed\n" ); } if( verbose != 0 ) mbedtls_printf( "\n" ); return( 0 ); } #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #undef F #undef P #undef S #endif /* MBEDTLS_MD5_C */ /********* Start of file library/md_wrap.c ************/ /** * \file md_wrap.c * * \brief Generic message digest wrapper for mbed TLS * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_MD_C) #if defined(MBEDTLS_MD2_C) #endif #if defined(MBEDTLS_MD4_C) #endif #if defined(MBEDTLS_MD5_C) #endif #if defined(MBEDTLS_RIPEMD160_C) #endif #if defined(MBEDTLS_SHA1_C) #endif #if defined(MBEDTLS_SHA256_C) #endif #if defined(MBEDTLS_SHA512_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #if defined(MBEDTLS_MD2_C) static void md2_starts_wrap( void *ctx ) { mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); } static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); } static void md2_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_md2_finish( (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 void md2_process_wrap( void *ctx, const unsigned char *data ) { ((void) data); mbedtls_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, md2_ctx_alloc, md2_ctx_free, md2_clone_wrap, md2_process_wrap, }; #endif /* MBEDTLS_MD2_C */ #if defined(MBEDTLS_MD4_C) static void md4_starts_wrap( void *ctx ) { mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); } static void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); } static void md4_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_md4_finish( (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 void md4_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_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, md4_ctx_alloc, md4_ctx_free, md4_clone_wrap, md4_process_wrap, }; #endif /* MBEDTLS_MD4_C */ #if defined(MBEDTLS_MD5_C) static void md5_starts_wrap( void *ctx ) { mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); } static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); } static void md5_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_md5_finish( (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 void md5_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_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, md5_ctx_alloc, md5_ctx_free, md5_clone_wrap, md5_process_wrap, }; #endif /* MBEDTLS_MD5_C */ #if defined(MBEDTLS_RIPEMD160_C) static void ripemd160_starts_wrap( void *ctx ) { mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); } static void ripemd160_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); } static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_ripemd160_finish( (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 void ripemd160_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_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, ripemd160_ctx_alloc, ripemd160_ctx_free, ripemd160_clone_wrap, ripemd160_process_wrap, }; #endif /* MBEDTLS_RIPEMD160_C */ #if defined(MBEDTLS_SHA1_C) static void sha1_starts_wrap( void *ctx ) { mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); } static void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); } static void sha1_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_sha1_finish( (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 void sha1_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_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, 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 void sha224_starts_wrap( void *ctx ) { mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); } static void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); } static void sha224_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); } static void sha224_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha256( 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 void sha224_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_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 void sha256_starts_wrap( void *ctx ) { mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); } static void sha256_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha256( 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 void sha384_starts_wrap( void *ctx ) { mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); } static void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); } static void sha384_finish_wrap( void *ctx, unsigned char *output ) { mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); } static void sha384_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha512( 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 void sha384_process_wrap( void *ctx, const unsigned char *data ) { mbedtls_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 void sha512_starts_wrap( void *ctx ) { mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); } static void sha512_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha512( 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 */ /********* Start of file library/memory_buffer_alloc.c ************/ /* * Buffer-based memory allocator * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) /* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C is dependent upon MBEDTLS_PLATFORM_C */ #include #if defined(MBEDTLS_MEMORY_BACKTRACE) #include #endif #if defined(MBEDTLS_THREADING_C) #endif /* Implementation that should never be optimized out by the compiler */ static void memory_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #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() { 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() { memory_header *prv = heap.first, *cur = heap.first->next; if( verify_header( heap.first ) != 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 ); } 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 && len / n != size ) 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 // 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; #if defined(MBEDTLS_MEMORY_BACKTRACE) free( old->trace ); #endif 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; #if defined(MBEDTLS_MEMORY_BACKTRACE) free( old->trace ); #endif 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 defined(MBEDTLS_MEMORY_BACKTRACE) hdr->trace = NULL; hdr->trace_count = 0; #endif 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() { return verify_chain(); } #if defined(MBEDTLS_MEMORY_DEBUG) void mbedtls_memory_buffer_alloc_status() { 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) ); memset( buf, 0, len ); #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( (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; } 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() { #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &heap.mutex ); #endif memory_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( ) { 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 */ /********* Start of file library/net.c ************/ /* * TCP/IP or UDP/IP networking functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_NET_C) #include #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif /* Enables getaddrinfo() & Co */ #define _WIN32_WINNT 0x0501 #include #include #include #if defined(_MSC_VER) #if defined(_WIN32_WCE) #pragma comment( lib, "ws2.lib" ) #else #pragma comment( lib, "ws2_32.lib" ) #endif #endif /* _MSC_VER */ /* Amalgamated Release Mappings */ #undef read #undef write #undef close #define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0) #define write(fd,buf,len) send(fd,(char*)buf,(int) len,0) #define close(fd) closesocket(fd) static int wsa_init_done = 0; #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ #include #include #include #include #if !VXWORKS #include #endif #include #include #include #include #include #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* Some MS functions want int and MSVC warns if we pass size_t, * but the standard fucntions use socklen_t, so cast only for MSVC */ #if defined(_MSC_VER) #define MSVC_INT_CAST (int) #else #define MSVC_INT_CAST #endif #include #include #include #if !VXWORKS #include #endif /* * Prepare for using the sockets interface */ static int net_prepare( void ) { #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) WSADATA wsaData; if( wsa_init_done == 0 ) { if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) return( MBEDTLS_ERR_NET_SOCKET_FAILED ); wsa_init_done = 1; } #else #if !defined(EFIX64) && !defined(EFI32) signal( SIGPIPE, SIG_IGN ); #endif #endif 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, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) { ret = 0; break; } close( ctx->fd ); ret = MBEDTLS_ERR_NET_CONNECT_FAILED; } freeaddrinfo( addr_list ); return( ret ); } /* * Create a listening socket on bind_ip:port */ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) { int n, ret; struct addrinfo hints, *addr_list, *cur; if( ( ret = net_prepare() ) != 0 ) return( ret ); /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ 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( bind_ip == NULL ) hints.ai_flags = AI_PASSIVE; if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); /* Try the sockaddrs until a binding 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; } n = 1; if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, #if VXWORKS (char *) &n, sizeof( n ) ) != 0 ) #else (const char *) &n, sizeof( n ) ) != 0 ) #endif { close( ctx->fd ); ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) { close( ctx->fd ); ret = MBEDTLS_ERR_NET_BIND_FAILED; continue; } /* Listen only makes sense for TCP */ if( proto == MBEDTLS_NET_PROTO_TCP ) { if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) { close( ctx->fd ); ret = MBEDTLS_ERR_NET_LISTEN_FAILED; continue; } } /* I we ever get there, it's a success */ ret = 0; break; } freeaddrinfo( addr_list ); return( ret ); } #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) /* * Check if the requested operation would be blocking on a non-blocking socket * and thus 'failed' with a negative return value. */ static int net_would_block( const mbedtls_net_context *ctx ) { ((void) ctx); return( WSAGetLastError() == WSAEWOULDBLOCK ); } #else /* * Check if the requested operation would be blocking on a non-blocking socket * and thus 'failed' with a negative return value. * * Note: on a blocking socket this function always returns 0! */ static int net_would_block( const mbedtls_net_context *ctx ) { /* * Never return 'WOULD BLOCK' on a non-blocking socket */ if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) return( 0 ); switch( errno ) { #if defined EAGAIN case EAGAIN: #endif #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif return( 1 ); } return( 0 ); } #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* * Accept a connection from a remote client */ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *ip_len ) { int ret; int type; struct sockaddr_storage client_addr; #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) socklen_t n = (socklen_t) sizeof( client_addr ); socklen_t type_len = (socklen_t) sizeof( type ); #else int n = (int) sizeof( client_addr ); int type_len = (int) sizeof( type ); #endif /* Is this a TCP or UDP socket? */ if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, (void *) &type, &type_len ) != 0 || ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) { return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); } if( type == SOCK_STREAM ) { /* TCP: actual accept() */ ret = client_ctx->fd = (int) accept( bind_ctx->fd, (struct sockaddr *) &client_addr, &n ); } else { /* UDP: wait for a message, but keep it in the queue */ char buf[1] = { 0 }; ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, (struct sockaddr *) &client_addr, &n ); #if defined(_WIN32) if( ret == SOCKET_ERROR && WSAGetLastError() == WSAEMSGSIZE ) { /* We know buf is too small, thanks, just peeking here */ ret = 0; } #endif } if( ret < 0 ) { if( net_would_block( bind_ctx ) != 0 ) return( MBEDTLS_ERR_SSL_WANT_READ ); return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); } /* UDP: hijack the listening socket to communicate with the client, * then bind a new socket to accept new connections */ if( type != SOCK_STREAM ) { struct sockaddr_storage local_addr; int one = 1; if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); client_ctx->fd = bind_ctx->fd; bind_ctx->fd = -1; /* In case we exit early */ n = sizeof( struct sockaddr_storage ); if( getsockname( client_ctx->fd, (struct sockaddr *) &local_addr, &n ) != 0 || ( bind_ctx->fd = (int) socket( local_addr.ss_family, SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || #if VXWORKS setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof( one ) ) != 0 ) #else setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &one, sizeof( one ) ) != 0 ) #endif { return( MBEDTLS_ERR_NET_SOCKET_FAILED ); } if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) { return( MBEDTLS_ERR_NET_BIND_FAILED ); } } if( client_ip != NULL ) { if( client_addr.ss_family == AF_INET ) { struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; *ip_len = sizeof( addr4->sin_addr.s_addr ); if( buf_size < *ip_len ) return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); } else { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; *ip_len = sizeof( addr6->sin6_addr.s6_addr ); if( buf_size < *ip_len ) return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); } } return( 0 ); } /* * Set the socket blocking or non-blocking */ int mbedtls_net_set_block( mbedtls_net_context *ctx ) { #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) u_long n = 0; return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); #else return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); #endif } int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) { #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) u_long n = 1; return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); #else return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); #endif } /* * Portable usleep helper */ void mbedtls_net_usleep( unsigned long usec ) { #if defined(_WIN32) Sleep( ( usec + 999 ) / 1000 ); #else struct timeval tv; tv.tv_sec = usec / 1000000; #if defined(__unix__) || defined(__unix) || \ ( defined(__APPLE__) && defined(__MACH__) ) tv.tv_usec = (suseconds_t) usec % 1000000; #else tv.tv_usec = usec % 1000000; #endif select( 0, NULL, NULL, NULL, &tv ); #endif } /* * 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) read( fd, buf, len ); if( ret < 0 ) { if( net_would_block( ctx ) != 0 ) return( MBEDTLS_ERR_SSL_WANT_READ ); #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) if( WSAGetLastError() == WSAECONNRESET ) return( MBEDTLS_ERR_NET_CONN_RESET ); #else if( errno == EPIPE || errno == ECONNRESET ) return( MBEDTLS_ERR_NET_CONN_RESET ); if( errno == EINTR ) return( MBEDTLS_ERR_SSL_WANT_READ ); #endif return( MBEDTLS_ERR_NET_RECV_FAILED ); } return( ret ); } /* * Read at most 'len' characters, blocking for at most 'timeout' ms */ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, uint32_t timeout ) { int ret; struct timeval tv; fd_set read_fds; int fd = ((mbedtls_net_context *) ctx)->fd; if( fd < 0 ) return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); FD_ZERO( &read_fds ); FD_SET( fd, &read_fds ); tv.tv_sec = timeout / 1000; tv.tv_usec = ( timeout % 1000 ) * 1000; ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); /* Zero fds ready means we timed out */ if( ret == 0 ) return( MBEDTLS_ERR_SSL_TIMEOUT ); if( ret < 0 ) { #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) if( WSAGetLastError() == WSAEINTR ) return( MBEDTLS_ERR_SSL_WANT_READ ); #else if( errno == EINTR ) return( MBEDTLS_ERR_SSL_WANT_READ ); #endif return( MBEDTLS_ERR_NET_RECV_FAILED ); } /* This call will not block */ return( mbedtls_net_recv( ctx, buf, len ) ); } /* * 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 ); #if VXWORKS ret = (int) write( fd, (char*) buf, len ); #else ret = (int) write( fd, buf, len ); #endif if( ret < 0 ) { if( net_would_block( ctx ) != 0 ) return( MBEDTLS_ERR_SSL_WANT_WRITE ); #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) if( WSAGetLastError() == WSAECONNRESET ) return( MBEDTLS_ERR_NET_CONN_RESET ); #else if( errno == EPIPE || errno == ECONNRESET ) return( MBEDTLS_ERR_NET_CONN_RESET ); if( errno == EINTR ) return( MBEDTLS_ERR_SSL_WANT_WRITE ); #endif 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 ); close( ctx->fd ); ctx->fd = -1; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && !defined(EFI32) /* Amalgamated Release Mappings */ #undef read #undef write #undef close #define read _read #define write _write #define close _close #endif #endif /* MBEDTLS_NET_C */ /********* Start of file library/oid.c ************/ /** * \file oid.c * * \brief Object Identifier (OID) database * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_OID_C) #include #include #if defined(MBEDTLS_PLATFORM_C) #else #define mbedtls_snprintf snprintf #endif #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) #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 ); \ } /* * 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) #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) /* * 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[] = { { { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, }, { { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, }, { { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, }, { { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, { { 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, }, { { 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, }, { { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, { { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, }, { { 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, }, { { 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, }, { { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, }, { { 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[] = { { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, MBEDTLS_ECP_DP_SECP192R1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, MBEDTLS_ECP_DP_SECP224R1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, MBEDTLS_ECP_DP_SECP256R1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, MBEDTLS_ECP_DP_SECP384R1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, MBEDTLS_ECP_DP_SECP521R1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, MBEDTLS_ECP_DP_SECP192K1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, MBEDTLS_ECP_DP_SECP224K1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, MBEDTLS_ECP_DP_SECP256K1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, MBEDTLS_ECP_DP_BP256R1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, MBEDTLS_ECP_DP_BP384R1, }, { { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, MBEDTLS_ECP_DP_BP512R1, }, { { 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[] = { { { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, MBEDTLS_MD_MD2, }, { { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, MBEDTLS_MD_MD4, }, { { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, MBEDTLS_MD_MD5, }, { { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, MBEDTLS_MD_SHA1, }, { { 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, }, { { 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, }, { { 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) #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 ) ); } /* Amalgamated Release Mappings */ #undef SAFE_SNPRINTF #endif /* MBEDTLS_OID_C */ /********* Start of file library/padlock.c ************/ /* * VIA PadLock support functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_PADLOCK_C) #include #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 */ /********* Start of file library/pem.c ************/ /* * Privacy Enhanced Mail (PEM) decoding * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif /* Implementation that should never be optimized out by the compiler */ static void pem_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #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 void 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; mbedtls_md5_init( &md5_ctx ); /* * key[ 0..15] = MD5(pwd || IV) */ mbedtls_md5_starts( &md5_ctx ); mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); mbedtls_md5_update( &md5_ctx, iv, 8 ); mbedtls_md5_finish( &md5_ctx, md5sum ); if( keylen <= 16 ) { memcpy( key, md5sum, keylen ); mbedtls_md5_free( &md5_ctx ); pem_zeroize( md5sum, 16 ); return; } memcpy( key, md5sum, 16 ); /* * key[16..23] = MD5(key[ 0..15] || pwd || IV]) */ mbedtls_md5_starts( &md5_ctx ); mbedtls_md5_update( &md5_ctx, md5sum, 16 ); mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); mbedtls_md5_update( &md5_ctx, iv, 8 ); mbedtls_md5_finish( &md5_ctx, md5sum ); use_len = 16; if( keylen < 32 ) use_len = keylen - 16; memcpy( key + 16, md5sum, use_len ); mbedtls_md5_free( &md5_ctx ); pem_zeroize( md5sum, 16 ); } #if defined(MBEDTLS_DES_C) /* * Decrypt with DES-CBC, using PBKDF1 for key derivation */ static void 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]; mbedtls_des_init( &des_ctx ); pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); mbedtls_des_setkey_dec( &des_ctx, des_key ); mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, des_iv, buf, buf ); mbedtls_des_free( &des_ctx ); pem_zeroize( des_key, 8 ); } /* * Decrypt with 3DES-CBC, using PBKDF1 for key derivation */ static void 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]; mbedtls_des3_init( &des3_ctx ); pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); mbedtls_des3_set3key_dec( &des3_ctx, des3_key ); mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, des3_iv, buf, buf ); mbedtls_des3_free( &des3_ctx ); pem_zeroize( des3_key, 24 ); } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) /* * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation */ static void 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]; mbedtls_aes_init( &aes_ctx ); pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, aes_iv, buf, buf ); mbedtls_aes_free( &aes_ctx ); pem_zeroize( aes_key, keylen ); } #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( 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( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) { enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; s1 += 23; if( pem_get_iv( s1, pem_iv, 8 ) != 0 ) return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); s1 += 16; } else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) { enc_alg = MBEDTLS_CIPHER_DES_CBC; s1 += 18; if( 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( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) { 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( 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_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_free( buf ); return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); } #if defined(MBEDTLS_DES_C) if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) 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 ) pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); #endif /* MBEDTLS_AES_C */ /* * 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 heurisitic to try detecting password mismatchs. */ if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) { mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); } #else 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 ) { mbedtls_free( ctx->buf ); mbedtls_free( ctx->info ); pem_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, *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( ( 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 */ /********* Start of file library/pk.c ************/ /* * Public Key abstraction layer * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_PK_C) #if defined(MBEDTLS_RSA_C) #endif #if defined(MBEDTLS_ECP_C) #endif #if defined(MBEDTLS_ECDSA_C) #endif /* Implementation that should never be optimized out by the compiler */ static void pk_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * Initialise a mbedtls_pk_context */ void mbedtls_pk_init( mbedtls_pk_context *ctx ) { if( ctx == NULL ) return; 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 || ctx->pk_info == NULL ) return; ctx->pk_info->ctx_free_func( ctx->pk_ctx ); pk_zeroize( ctx, sizeof( mbedtls_pk_context ) ); } /* * 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 ) { if( ctx == NULL || 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; if( ctx == 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; 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 ) { /* null or NONE context can't do anything */ 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 ); } /* * 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 ) { if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); 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 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 ) { if( ctx == NULL || 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( 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 } /* 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 */ 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 ) { if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); 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 ) ); } /* * 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 ) { if( ctx == NULL || 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 ) { if( ctx == NULL || 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 ) { if( pub == NULL || pub->pk_info == NULL || prv == 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 ) { 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 ) { if( ctx == NULL || 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 */ /********* Start of file library/pk_wrap.c ************/ /* * Public Key abstraction layer: wrapper functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_PK_C) /* Even if RSA not activated, for the sake of RSA-alt */ #include #if defined(MBEDTLS_ECP_C) #endif #if defined(MBEDTLS_ECDSA_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* Implementation that should never be optimized out by the compiler */ static void pk_wrap_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #endif #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 ) { return( 8 * ((const mbedtls_rsa_context *) ctx)->len ); } 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; if( sig_len < ((mbedtls_rsa_context *) ctx)->len ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( ( ret = mbedtls_rsa_pkcs1_verify( (mbedtls_rsa_context *) ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, md_alg, (unsigned int) hash_len, hash, sig ) ) != 0 ) return( ret ); if( sig_len > ((mbedtls_rsa_context *) ctx)->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 ) { *sig_len = ((mbedtls_rsa_context *) ctx)->len; return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, 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 ) { if( ilen != ((mbedtls_rsa_context *) ctx)->len ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, 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 ) { *olen = ((mbedtls_rsa_context *) ctx)->len; if( *olen > osize ) return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); return( mbedtls_rsa_pkcs1_encrypt( (mbedtls_rsa_context *) ctx, 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, rsa_decrypt_wrap, rsa_encrypt_wrap, rsa_check_pair_wrap, rsa_alloc_wrap, rsa_free_wrap, 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 ); } #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, #else NULL, NULL, #endif NULL, NULL, eckey_check_pair, eckey_alloc_wrap, eckey_free_wrap, 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, NULL, NULL, eckey_check_pair, eckey_alloc_wrap, /* Same underlying key structure */ eckey_free_wrap, /* Same underlying key structure */ 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 ) ); } 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 ); } 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, NULL, NULL, eckey_check_pair, /* Compatible key structures */ ecdsa_alloc_wrap, ecdsa_free_wrap, 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; *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 ) { pk_wrap_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, 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, NULL, }; #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #endif /* MBEDTLS_PK_C */ /********* Start of file library/pkcs11.c ************/ /** * \file pkcs11.c * * \brief Wrapper for PKCS#11 library libpkcs11-helper * * \author Adriaan de Jong * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if defined(MBEDTLS_PKCS11_C) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #include 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) */ /********* Start of file library/pkcs12.c ************/ /* * PKCS#12 Personal Information Exchange Syntax * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_PKCS12_C) #include #if defined(MBEDTLS_ARC4_C) #endif #if defined(MBEDTLS_DES_C) #endif /* Implementation that should never be optimized out by the compiler */ static void pkcs_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } 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; 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: pkcs_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: pkcs_zeroize( key, sizeof( key ) ); pkcs_zeroize( iv, sizeof( iv ) ); mbedtls_cipher_free( &cipher_ctx ); return( ret ); } 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: pkcs_zeroize( salt_block, sizeof( salt_block ) ); pkcs_zeroize( pwd_block, sizeof( pwd_block ) ); pkcs_zeroize( hash_block, sizeof( hash_block ) ); pkcs_zeroize( hash_output, sizeof( hash_output ) ); mbedtls_md_free( &md_ctx ); return( ret ); } #endif /* MBEDTLS_PKCS12_C */ /********* Start of file library/pkcs5.c ************/ /** * \file pkcs5.c * * \brief PKCS#5 functions * * \author Mathias Olsson * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_PKCS5_C) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif 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_CMP( MBEDTLS_OID_HMAC_SHA1, &prf_alg_oid ) != 0 ) return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); *md_type = MBEDTLS_MD_SHA1; 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 ); } 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( iteration_count > 0xFFFFFFFF ) return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); 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" ); } mbedtls_printf( "\n" ); exit: mbedtls_md_free( &sha1_ctx ); return( ret ); } #endif /* MBEDTLS_SHA1_C */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_PKCS5_C */ /********* Start of file library/pkparse.c ************/ /* * Public Key layer for parsing key files and structures * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_PK_PARSE_C) #include #if defined(MBEDTLS_RSA_C) #endif #if defined(MBEDTLS_ECP_C) #endif #if defined(MBEDTLS_ECDSA_C) #endif #if defined(MBEDTLS_PEM_PARSE_C) #endif #if defined(MBEDTLS_PKCS5_C) #endif #if defined(MBEDTLS_PKCS12_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #if defined(MBEDTLS_FS_IO) /* Implementation that should never be optimized out by the compiler */ static void pkparse_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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; 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_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; 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 ) ); pkparse_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; if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) return( ret ); ret = mbedtls_pk_parse_public_key( ctx, buf, n ); pkparse_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; /* 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 ); if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); if( *p != end ) return( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); rsa->len = mbedtls_mpi_size( &rsa->N ); 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; 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) /* * 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; size_t len; unsigned char *p, *end; 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, &rsa->ver ) ) != 0 ) { return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); } if( rsa->ver != 0 ) { return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); } if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) { mbedtls_rsa_free( rsa ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); } rsa->len = mbedtls_mpi_size( &rsa->N ); if( p != end ) { mbedtls_rsa_free( rsa ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); } if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) { mbedtls_rsa_free( rsa ); return( ret ); } return( 0 ); } #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 ); } /* * 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 */ 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 PrivatKeyInfo 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 */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) static int pk_parse_key_pkcs8_encrypted_der( mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) { int ret, decrypted = 0; size_t len; unsigned char buf[2048]; 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 memset( buf, 0, sizeof( buf ) ); p = (unsigned char *) key; end = p + keylen; if( pwdlen == 0 ) return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); /* * This function parses the EncryptedPrivatKeyInfo 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 ); if( len > sizeof( buf ) ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); /* * Decrypt EncryptedData with appropriate PDE */ #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; mbedtls_pem_init( &pem ); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if( keylen == 0 || 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 ) { if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 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( keylen == 0 || 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 ) { if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); 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( keylen == 0 || 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( keylen == 0 || 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) ret); ((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) if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, pwd, pwdlen ) ) == 0 ) { return( 0 ); } mbedtls_pk_free( 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 ); #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( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) { return( 0 ); } mbedtls_pk_free( pk ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) { return( 0 ); } mbedtls_pk_free( pk ); #endif /* MBEDTLS_ECP_C */ 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_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; mbedtls_pem_init( &pem ); /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if( keylen == 0 || 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 */ key = pem.buf; keylen = pem.buflen; } else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) { mbedtls_pem_free( &pem ); return( ret ); } #endif /* MBEDTLS_PEM_PARSE_C */ p = (unsigned char *) key; ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_free( &pem ); #endif return( ret ); } #endif /* MBEDTLS_PK_PARSE_C */ /********* Start of file library/pkwrite.c ************/ /* * Public Key layer for writing key files and structures * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_PK_WRITE_C) #include #if defined(MBEDTLS_RSA_C) #endif #if defined(MBEDTLS_ECP_C) #endif #if defined(MBEDTLS_ECDSA_C) #endif #if defined(MBEDTLS_PEM_WRITE_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #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_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N ) ); 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 ); } #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; #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; 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 = buf + size; size_t len = 0; #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) { mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) ); 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: write as MPI then fix tag */ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); *c = MBEDTLS_ASN1_OCTET_STRING; /* 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; 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; 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 */ /********* Start of file library/platform.c ************/ /* * Platform abstraction layer * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_MEMORY) #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 */ void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), void (*free_func)( void * ) ) { mbedtls_calloc = calloc_func; mbedtls_free = free_func; return( 0 ); } #endif /* MBEDTLS_PLATFORM_MEMORY */ #if defined(_WIN32) #include 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) 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 */ #endif /* MBEDTLS_PLATFORM_C */ /********* Start of file library/ripemd160.c ************/ /* * RIPE MD-160 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_RIPEMD160_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ /* * 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 /* Implementation that should never be optimized out by the compiler */ static void ripemd_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } 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; ripemd_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 */ void mbedtls_ripemd160_starts( 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; } #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) /* * Process one block */ void mbedtls_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 ) \ a += f( b, c, d ) + X[r] + k; \ a = S( a, s ) + e; \ c = S( c, 10 ); #define P2( a, b, c, d, e, r, s, rp, sp ) \ 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 ); #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; } #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ /* * RIPEMD-160 process buffer */ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; uint32_t left; if( ilen == 0 ) return; 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 ); mbedtls_ripemd160_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { mbedtls_ripemd160_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), input, ilen ); } } 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 */ void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ) { 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 ); mbedtls_ripemd160_update( ctx, ripemd160_padding, padn ); mbedtls_ripemd160_update( ctx, msglen, 8 ); 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 ); } /* * output = RIPEMD-160( input buffer ) */ void mbedtls_ripemd160( const unsigned char *input, size_t ilen, unsigned char output[20] ) { mbedtls_ripemd160_context ctx; mbedtls_ripemd160_init( &ctx ); mbedtls_ripemd160_starts( &ctx ); mbedtls_ripemd160_update( &ctx, input, ilen ); mbedtls_ripemd160_finish( &ctx, output ); mbedtls_ripemd160_free( &ctx ); } #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 #define KEYS 2 static const char *ripemd160_test_input[TESTS] = { "", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", }; 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; 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 ); mbedtls_ripemd160( (const unsigned char *) ripemd160_test_input[i], strlen( ripemd160_test_input[i] ), output ); if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } if( verbose != 0 ) mbedtls_printf( "passed\n" ); } return( 0 ); } #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #undef F #undef K #undef F1 #undef F2 #undef F3 #undef F4 #undef F5 #undef P #undef S #endif /* MBEDTLS_RIPEMD160_C */ /********* Start of file library/rsa.c ************/ /* * The RSA public-key cryptosystem * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ /* * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. * * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_RSA_C) #include #if defined(MBEDTLS_PKCS1_V21) #endif #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) #include #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #define mbedtls_calloc calloc #define mbedtls_free free #endif /* * Initialize an RSA context */ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, int padding, int hash_id ) { 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 ) { ctx->padding = padding; ctx->hash_id = hash_id; } #if defined(MBEDTLS_GENPRIME) /* * Generate an RSA keypair */ 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 P1, Q1, H, G; if( f_rng == NULL || nbits < 128 || exponent < 3 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); do { MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mbedtls_mpi_swap( &ctx->P, &ctx->Q ); if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) continue; MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) continue; MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); } while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); /* * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; cleanup: mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); 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 ) { if( !ctx->N.p || !ctx->E.p ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); if( ( ctx->N.p[0] & 1 ) == 0 || ( ctx->E.p[0] & 1 ) == 0 ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); if( 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 a private RSA key */ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) { int ret; mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) return( ret ); if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); /* * Check for a valid PKCS1v2 private key */ if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || mbedtls_mpi_cmp_int( &I, 1 ) != 0 || mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } cleanup: mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) return( ret ); if( ret != 0 ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); 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 ) { 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; 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 ); } /* * 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; mbedtls_mpi T, T1, T2; /* Make sure we have private key info, prevent possible misuse */ if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); #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; } 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 ) ); } #if defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); #else /* * faster decryption using the CRT * * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q */ MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P */ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); /* * T = T2 + T * Q */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); #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 ) ); } 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( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); 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 void 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; 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; mbedtls_md_starts( md_ctx ); mbedtls_md_update( md_ctx, src, slen ); mbedtls_md_update( md_ctx, counter, 4 ); mbedtls_md_finish( md_ctx, mask ); for( i = 0; i < use_len; ++i ) *p++ ^= mask[i]; counter[3]++; dlen -= use_len; } } #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; 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 ); if( 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 // mbedtls_md( md_info, label, label_len, p ); p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; memcpy( p, input, ilen ); mbedtls_md_init( &md_ctx ); mbedtls_md_setup( &md_ctx, md_info, 0 ); // maskedDB: Apply dbMask to DB // mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, &md_ctx ); // maskedSeed: Apply seedMask to seed // mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, &md_ctx ); mbedtls_md_free( &md_ctx ); 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; if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); if( f_rng == NULL ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; if( olen < ilen + 11 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); nb_pad = olen - 3 - ilen; *p++ = 0; if( mode == MBEDTLS_RSA_PUBLIC ) { *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 ) { 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; /* * 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 ); /* * 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 ) return( ret ); /* * Unmask data and generate lHash */ hlen = mbedtls_md_get_size( md_info ); mbedtls_md_init( &md_ctx ); mbedtls_md_setup( &md_ctx, md_info, 0 ); /* Generate lHash */ mbedtls_md( md_info, label, label_len, lhash ); /* seed: Apply seedMask to maskedSeed */ mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, &md_ctx ); /* DB: Apply dbMask to maskedDB */ mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, &md_ctx ); mbedtls_md_free( &md_ctx ); /* * 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 ) return( MBEDTLS_ERR_RSA_INVALID_PADDING ); if( ilen - ( p - buf ) > output_max_len ) return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (p - buf); memcpy( output, p, *olen ); return( 0 ); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * 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, pad_count = 0, i; unsigned char *p, bad, pad_done = 0; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); ilen = ctx->len; 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 ) return( ret ); p = buf; bad = 0; /* * Check and get padding len in "constant-time" */ bad |= *p++; /* First byte must be 0 */ /* This test does not depend on secret data */ if( mode == MBEDTLS_RSA_PRIVATE ) { bad |= *p++ ^ MBEDTLS_RSA_CRYPT; /* Get padding len, but always read till end of buffer * (minus one, for the 00 byte) */ for( i = 0; i < ilen - 3; i++ ) { pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; } p += pad_count; bad |= *p++; /* Must be zero */ } else { bad |= *p++ ^ MBEDTLS_RSA_SIGN; /* Get padding len, but always read till end of buffer * (minus one, for the 00 byte) */ for( i = 0; i < ilen - 3; i++ ) { pad_done |= ( p[i] != 0xFF ); pad_count += ( pad_done == 0 ); } p += pad_count; bad |= *p++; /* Must be zero */ } if( bad ) return( MBEDTLS_ERR_RSA_INVALID_PADDING ); if( ilen - ( p - buf ) > output_max_len ) return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (p - buf); memcpy( output, p, *olen ); return( 0 ); } #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) { 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]; unsigned int slen, hlen, offset = 0; int ret; size_t msb; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; 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 ); slen = hlen; if( olen < hlen + slen + 2 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 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 * 2 - 2; *p++ = 0x01; memcpy( p, salt, slen ); p += slen; mbedtls_md_init( &md_ctx ); mbedtls_md_setup( &md_ctx, md_info, 0 ); // Generate H = Hash( M' ) // mbedtls_md_starts( &md_ctx ); mbedtls_md_update( &md_ctx, p, 8 ); mbedtls_md_update( &md_ctx, hash, hashlen ); mbedtls_md_update( &md_ctx, salt, slen ); mbedtls_md_finish( &md_ctx, p ); // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) offset = 1; // maskedDB: Apply dbMask to DB // mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); mbedtls_md_free( &md_ctx ); msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; sig[0] &= 0xFF >> ( olen * 8 - msb ); p += hlen; *p++ = 0xBC; 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 */ /* * 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 ) { size_t nb_pad, olen, oid_size = 0; unsigned char *p = sig; const char *oid = NULL; unsigned char *sig_try = NULL, *verif = NULL; size_t i; unsigned char diff; volatile unsigned char diff_no_optimize; int ret; if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; nb_pad = olen - 3; 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 ); nb_pad -= 10 + oid_size; hashlen = mbedtls_md_get_size( md_info ); } nb_pad -= hashlen; if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); *p++ = 0; *p++ = MBEDTLS_RSA_SIGN; memset( p, 0xFF, nb_pad ); p += nb_pad; *p++ = 0; if( md_alg == MBEDTLS_MD_NONE ) { memcpy( p, hash, hashlen ); } else { /* * 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( mode == MBEDTLS_RSA_PUBLIC ) return( mbedtls_rsa_public( ctx, sig, sig ) ); /* * 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 ) ); /* Compare in constant time just in case */ for( diff = 0, i = 0; i < ctx->len; i++ ) diff |= verif[i] ^ sig[i]; diff_no_optimize = diff; if( diff_no_optimize != 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 ) { 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 buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char result[MBEDTLS_MD_MAX_SIZE]; unsigned char zeros[8]; unsigned int hlen; size_t slen, msb; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; 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 ); slen = siglen - hlen - 1; /* Currently length of salt + padding */ memset( zeros, 0, 8 ); // Note: EMSA-PSS verification is over the length of N - 1 bits // msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) { p++; siglen -= 1; } if( buf[0] >> ( 8 - siglen * 8 + msb ) ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_md_init( &md_ctx ); mbedtls_md_setup( &md_ctx, md_info, 0 ); mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); buf[0] &= 0xFF >> ( siglen * 8 - msb ); while( p < buf + siglen && *p == 0 ) p++; if( p == buf + siglen || *p++ != 0x01 ) { mbedtls_md_free( &md_ctx ); return( MBEDTLS_ERR_RSA_INVALID_PADDING ); } /* Actual salt len */ slen -= p - buf; if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && slen != (size_t) expected_salt_len ) { mbedtls_md_free( &md_ctx ); return( MBEDTLS_ERR_RSA_INVALID_PADDING ); } // Generate H = Hash( M' ) // mbedtls_md_starts( &md_ctx ); mbedtls_md_update( &md_ctx, zeros, 8 ); mbedtls_md_update( &md_ctx, hash, hashlen ); mbedtls_md_update( &md_ctx, p, slen ); mbedtls_md_finish( &md_ctx, result ); mbedtls_md_free( &md_ctx ); if( memcmp( p + slen, result, hlen ) == 0 ) return( 0 ); else return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); } /* * 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 = ( 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; size_t len, siglen, asn1_len; unsigned char *p, *end; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; mbedtls_md_type_t msg_md_alg; const mbedtls_md_info_t *md_info; mbedtls_asn1_buf oid; if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 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( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN ) return( MBEDTLS_ERR_RSA_INVALID_PADDING ); while( *p != 0 ) { if( p >= buf + siglen - 1 || *p != 0xFF ) return( MBEDTLS_ERR_RSA_INVALID_PADDING ); p++; } p++; len = siglen - ( p - buf ); if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) { if( memcmp( p, hash, hashlen ) == 0 ) return( 0 ); else return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); } 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 ); end = p + len; // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure // if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( asn1_len + 2 != len ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( asn1_len + 6 + hashlen != len ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); oid.p = p; p += oid.len; if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( md_alg != msg_md_alg ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); /* * assume the algorithm parameters must be NULL */ if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( asn1_len != hashlen ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); if( memcmp( p, hash, hashlen ) != 0 ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); p += hashlen; if( p != end ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); return( 0 ); } #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 ) { 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; 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 ) ); 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->RN, &src->RN ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); 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 ) { mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D ); mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &ctx->mutex ); #endif } #if defined(MBEDTLS_SELF_TEST) /* * 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 RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ "3C94D22288ACD763FD8E5600ED4A702D" \ "F84198A5F06C2E72236AE490C93F07F8" \ "3CC559CD27BC2D1CA488811730BB5725" #define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ "D8AAEA56749EA28623272E4F7D0592AF" \ "7C1F1313CAC9471B5C523BFE592F517B" \ "407A1BD76C164B93DA2D32A383E58357" #define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ "F38D18D2B2F0E2DD275AA977E2BF4411" \ "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ "A74206CEC169D74BF5A8C50D6F48EA08" #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_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); rsa.len = KEY_LEN; MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); 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" ); return( 1 ); } 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" ); return( 1 ); } 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" ); return( 1 ); } if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } if( verbose != 0 ) mbedtls_printf( "passed\n" ); #if defined(MBEDTLS_SHA1_C) if( verbose != 0 ) mbedtls_printf( "PKCS#1 data sign : " ); mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); 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" ); return( 1 ); } 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" ); return( 1 ); } if( verbose != 0 ) mbedtls_printf( "passed\n" ); #endif /* MBEDTLS_SHA1_C */ if( verbose != 0 ) mbedtls_printf( "\n" ); cleanup: mbedtls_rsa_free( &rsa ); #else /* MBEDTLS_PKCS1_V15 */ ((void) verbose); #endif /* MBEDTLS_PKCS1_V15 */ return( ret ); } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_RSA_C */ /********* Start of file library/sha1.c ************/ /* * FIPS-180-1 compliant SHA-1 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_SHA1_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_SHA1_ALT) /* Implementation that should never be optimized out by the compiler */ static void sha1_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 ) { memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); } void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) { if( ctx == NULL ) return; sha1_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); } void mbedtls_sha1_clone( mbedtls_sha1_context *dst, const mbedtls_sha1_context *src ) { *dst = *src; } /* * SHA-1 context setup */ void mbedtls_sha1_starts( mbedtls_sha1_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; } #if !defined(MBEDTLS_SHA1_PROCESS_ALT) void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) { uint32_t temp, W[16], A, B, C, D, E; 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) \ { \ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ } 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; } #endif /* !MBEDTLS_SHA1_PROCESS_ALT */ /* * SHA-1 process buffer */ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; uint32_t left; if( ilen == 0 ) return; 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 ); mbedtls_sha1_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { mbedtls_sha1_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); } static const unsigned char sha1_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 }; /* * SHA-1 final digest */ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) { 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_BE( high, msglen, 0 ); PUT_UINT32_BE( low, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); mbedtls_sha1_update( ctx, sha1_padding, padn ); mbedtls_sha1_update( ctx, msglen, 8 ); 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 ); } #endif /* !MBEDTLS_SHA1_ALT */ /* * output = SHA-1( input buffer ) */ void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) { mbedtls_sha1_context ctx; mbedtls_sha1_init( &ctx ); mbedtls_sha1_starts( &ctx ); mbedtls_sha1_update( &ctx, input, ilen ); mbedtls_sha1_finish( &ctx, output ); mbedtls_sha1_free( &ctx ); } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-1 test vectors */ static const unsigned char sha1_test_buf[3][57] = { { "abc" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "" } }; static const int 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 ); mbedtls_sha1_starts( &ctx ); if( i == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) mbedtls_sha1_update( &ctx, buf, buflen ); } else mbedtls_sha1_update( &ctx, sha1_test_buf[i], sha1_test_buflen[i] ); mbedtls_sha1_finish( &ctx, sha1sum ); if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 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_sha1_free( &ctx ); return( ret ); } #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #undef F #undef P #undef R #undef S #endif /* MBEDTLS_SHA1_C */ /********* Start of file library/sha256.c ************/ /* * FIPS-180-2 compliant SHA-256 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_SHA256_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_SHA256_ALT) /* Implementation that should never be optimized out by the compiler */ static void sha256_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 ) { memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); } void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) { if( ctx == NULL ) return; sha256_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); } void mbedtls_sha256_clone( mbedtls_sha256_context *dst, const mbedtls_sha256_context *src ) { *dst = *src; } /* * SHA-256 context setup */ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) { 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; } #if !defined(MBEDTLS_SHA256_PROCESS_ALT) /* Amalgamated Release Mappings */ #define K K256 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) \ { \ temp1 = h + S3(e) + F1(e,f,g) + K + x; \ temp2 = S2(a) + F0(a,b,c); \ d += temp1; h = temp1 + temp2; \ } void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) { uint32_t temp1, temp2, W[64]; uint32_t A[8]; unsigned int i; 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]; } #endif /* !MBEDTLS_SHA256_PROCESS_ALT */ /* * SHA-256 process buffer */ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; uint32_t left; if( ilen == 0 ) return; 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 ); mbedtls_sha256_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { mbedtls_sha256_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); } static const unsigned char sha256_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 }; /* * SHA-256 final digest */ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) { 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_BE( high, msglen, 0 ); PUT_UINT32_BE( low, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); mbedtls_sha256_update( ctx, sha256_padding, padn ); mbedtls_sha256_update( ctx, msglen, 8 ); 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 ); } #endif /* !MBEDTLS_SHA256_ALT */ /* * output = SHA-256( input buffer ) */ void mbedtls_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ) { mbedtls_sha256_context ctx; mbedtls_sha256_init( &ctx ); mbedtls_sha256_starts( &ctx, is224 ); mbedtls_sha256_update( &ctx, input, ilen ); mbedtls_sha256_finish( &ctx, output ); mbedtls_sha256_free( &ctx ); } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ static const unsigned char sha256_test_buf[3][57] = { { "abc" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "" } }; static const int 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[1024]; unsigned char sha256sum[32]; mbedtls_sha256_context ctx; 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 ); mbedtls_sha256_starts( &ctx, k ); if( j == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) mbedtls_sha256_update( &ctx, buf, buflen ); } else mbedtls_sha256_update( &ctx, sha256_test_buf[j], sha256_test_buflen[j] ); mbedtls_sha256_finish( &ctx, sha256sum ); if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 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_sha256_free( &ctx ); return( ret ); } #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #undef P #undef R #undef SHR #undef ROTR #undef S0 #undef S1 #undef S2 #undef S3 #undef F0 #undef F1 #undef K #endif /* MBEDTLS_SHA256_C */ /********* Start of file library/sha512.c ************/ /* * FIPS-180-2 compliant SHA-384/512 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_SHA512_C) #if defined(_MSC_VER) || defined(__WATCOMC__) #define UL64(x) x##ui64 #else #define UL64(x) x##ULL #endif #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_SHA512_ALT) /* Implementation that should never be optimized out by the compiler */ static void sha512_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 */ /* * Round constants */ /* Amalgamated Release Mappings */ #define K K512 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) }; void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); } void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) { if( ctx == NULL ) return; sha512_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); } void mbedtls_sha512_clone( mbedtls_sha512_context *dst, const mbedtls_sha512_context *src ) { *dst = *src; } /* * SHA-512 context setup */ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) { 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; } #if !defined(MBEDTLS_SHA512_PROCESS_ALT) void mbedtls_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; #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) \ { \ temp1 = h + S3(e) + F1(e,f,g) + K + x; \ temp2 = S2(a) + F0(a,b,c); \ d += temp1; h = temp1 + temp2; \ } 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; } #endif /* !MBEDTLS_SHA512_PROCESS_ALT */ /* * SHA-512 process buffer */ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; unsigned int left; if( ilen == 0 ) return; 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 ); mbedtls_sha512_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 128 ) { mbedtls_sha512_process( ctx, input ); input += 128; ilen -= 128; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); } static const unsigned char sha512_padding[128] = { 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, 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, 0 }; /* * SHA-512 final digest */ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ) { size_t last, padn; uint64_t high, low; unsigned char msglen[16]; high = ( ctx->total[0] >> 61 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_UINT64_BE( high, msglen, 0 ); PUT_UINT64_BE( low, msglen, 8 ); last = (size_t)( ctx->total[0] & 0x7F ); padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); mbedtls_sha512_update( ctx, sha512_padding, padn ); mbedtls_sha512_update( ctx, msglen, 16 ); 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 ); } } #endif /* !MBEDTLS_SHA512_ALT */ /* * output = SHA-512( input buffer ) */ void mbedtls_sha512( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 ) { mbedtls_sha512_context ctx; mbedtls_sha512_init( &ctx ); mbedtls_sha512_starts( &ctx, is384 ); mbedtls_sha512_update( &ctx, input, ilen ); mbedtls_sha512_finish( &ctx, output ); mbedtls_sha512_free( &ctx ); } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ static const unsigned char sha512_test_buf[3][113] = { { "abc" }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, { "" } }; static const int 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[1024]; unsigned char sha512sum[64]; mbedtls_sha512_context ctx; 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 ); mbedtls_sha512_starts( &ctx, k ); if( j == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) mbedtls_sha512_update( &ctx, buf, buflen ); } else mbedtls_sha512_update( &ctx, sha512_test_buf[j], sha512_test_buflen[j] ); mbedtls_sha512_finish( &ctx, sha512sum ); if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 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_sha512_free( &ctx ); return( ret ); } #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #undef P #undef R #undef SHR #undef ROTR #undef S0 #undef S1 #undef S2 #undef S3 #undef F0 #undef F1 #undef K #endif /* MBEDTLS_SHA512_C */ /********* Start of file library/ssl_cache.c ************/ /* * SSL session cache implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_SSL_CACHE_C) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif 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) time_t t = 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) time_t t = 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 } #endif /* MBEDTLS_SSL_CACHE_C */ /********* Start of file library/ssl_ciphersuites.c ************/ /** * \file ssl_ciphersuites.c * * \brief SSL ciphersuites for mbed TLS * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_SSL_TLS_C) // #include #include /* * Ordered from most preferred to least preferred in terms of security. * * Current rule (except rc4, 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: * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES * 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 /* 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 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 remaining >= 128-bit ephemeral 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, /* The PSK ephemeral suites */ 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_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_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, /* 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 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 remaining >= 128-bit suites */ 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, /* The RSA PSK suites */ 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_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_3DES_EDE_CBC_SHA, /* The PSK suites */ 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_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_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_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 */ { 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]; /* Amalgamated Release Mappings */ #define supported_init suites_supported_init static int supported_init = 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++ ) { #if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) const mbedtls_ssl_ciphersuite_t *cs_info; if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) #else if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) #endif *(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 ); } } #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) 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: return( 1 ); default: return( 0 ); } } #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ #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 */ /* Amalgamated Release Mappings */ #undef supported_init #endif /* MBEDTLS_SSL_TLS_C */ /********* Start of file library/ssl_cli.c ************/ /* * SSLv3/TLSv1 client-side functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_SSL_CLI_C) #include #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #if !VXWORKS #include #endif #if defined(MBEDTLS_HAVE_TIME) #include #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) /* Implementation that should never be optimized out by the compiler */ static void ssl_cli_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) static void ssl_cli_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_MAX_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; } /* * 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_cli_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_MAX_CONTENT_LEN; *olen = 0; 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_cli_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_MAX_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_cli_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_MAX_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++ ) { info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #else for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) { #endif 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++ ) { info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #else for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) { #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_cli_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_MAX_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_cli_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_MAX_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_cli_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_MAX_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_cli_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_MAX_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_cli_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_MAX_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_cli_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_MAX_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_cli_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_MAX_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_cli_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_MAX_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) 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 = 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 ); } 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; 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( ciphersuite_info == NULL ) continue; if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) continue; #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) continue; #endif #if defined(MBEDTLS_ARC4_C) if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) continue; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) continue; #endif MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", ciphersuites[i] ) ); n++; *p++ = (unsigned char)( ciphersuites[i] >> 8 ); *p++ = (unsigned char)( ciphersuites[i] ); } /* * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) #endif { *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 ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); #if defined(MBEDTLS_ZLIB_SUPPORT) offer_compress = 1; #else offer_compress = 0; #endif /* * We don't support compression with DTLS right now: is 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_cli_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl_cli_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_cli_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) ssl_cli_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; ssl_cli_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ssl_cli_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ssl_cli_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) ssl_cli_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) ssl_cli_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) ssl_cli_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_ALPN) ssl_cli_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) ssl_cli_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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); return( 0 ); } static int ssl_cli_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { int ret; #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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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_cli_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 ) { 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_cli_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 ) { 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_cli_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 ) { 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_cli_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 ) { 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_cli_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 ) { 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; list_size = buf[0]; if( list_size + 1 != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } 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" ) ); 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 ); return( ret ); } return( 0 ); } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) static int ssl_cli_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 ) 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 ) return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); list_len = ( buf[0] << 8 ) | buf[1]; if( list_len != len - 2 ) return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); name_len = buf[2]; if( name_len != list_len - 1 ) 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 ); } } 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" ) ); /* * 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++; 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; #if defined(MBEDTLS_DEBUG_C) uint32_t t; #endif MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); buf = ssl->in_msg; if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { 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" ) ); return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello 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" ) ); 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 ); } #if defined(MBEDTLS_DEBUG_C) t = ( (uint32_t) buf[2] << 24 ) | ( (uint32_t) buf[3] << 16 ) | ( (uint32_t) buf[4] << 8 ) | ( (uint32_t) buf[5] ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); #endif 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" ) ); 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" ) ); 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" ) ); 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 ) ); 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 ) ); 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 = 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 ); 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] ) ); suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); if( suite_info == NULL #if defined(MBEDTLS_ARC4_C) || ( ssl->conf->arc4_disabled && suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) #endif ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); i = 0; while( 1 ) { if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == ssl->session_negotiate->ciphersuite ) { break; } } 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" ) ); 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" ) ); 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_cli_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_cli_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_cli_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_cli_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_cli_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_cli_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_cli_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 ) { if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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; curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.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, ssl->handshake->ecdh_ctx.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_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.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 ); 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>; */ len = (*p)[0] << 8 | (*p)[1]; *p += 2; if( (*p) + len > end ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } // TODO: Retrieve PSK identity hint and callback to app // *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_MAX_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_MAX_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 " "that was not offered" ) ); 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_cli_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, *end; 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_cli_get_ecdh_params_from_cert( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_cli_get_ecdh_params_from_cert", ret ); 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( ( ret = mbedtls_ssl_read_record( ssl ) ) != 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" ) ); 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 ) { ssl->record_read = 1; goto exit; } MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } 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" ) ); 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" ) ); 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" ) ); 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 ); 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_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) { 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; /* * 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" ) ); 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" ) ); 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 */ sig_len = ( p[0] << 8 ) | p[1]; p += 2; if( end != p + sig_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); 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 ) { mbedtls_md5_context mbedtls_md5; mbedtls_sha1_context mbedtls_sha1; mbedtls_md5_init( &mbedtls_md5 ); mbedtls_sha1_init( &mbedtls_sha1 ); hashlen = 36; /* * 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); */ mbedtls_md5_starts( &mbedtls_md5 ); mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); mbedtls_md5_update( &mbedtls_md5, params, params_len ); mbedtls_md5_finish( &mbedtls_md5, hash ); mbedtls_sha1_starts( &mbedtls_sha1 ); mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); mbedtls_sha1_update( &mbedtls_sha1, params, params_len ); mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); mbedtls_md5_free( &mbedtls_md5 ); mbedtls_sha1_free( &mbedtls_sha1 ); } 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 ) { mbedtls_md_context_t ctx; mbedtls_md_init( &ctx ); /* Info from md_alg will be used instead */ hashlen = 0; /* * digitally-signed struct { * opaque client_random[32]; * opaque server_random[32]; * ServerDHParams params; * }; */ if( ( ret = mbedtls_md_setup( &ctx, mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); return( ret ); } mbedtls_md_starts( &ctx ); mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); mbedtls_md_update( &ctx, params, params_len ); mbedtls_md_finish( &ctx, hash ); mbedtls_md_free( &ctx ); } 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 != 0 ? hashlen : (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); if( ssl->session_negotiate->peer_cert == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); 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" ) ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, md_alg, hash, hashlen, p, sig_len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); return( ret ); } } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ exit: ssl->state++; MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); return( 0 ); } #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ !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_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( 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 parse certificate request" ) ); ssl->state++; return( 0 ); } MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } #else static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) { int ret; unsigned char *buf, *p; size_t n = 0, m = 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( 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 parse certificate request" ) ); ssl->state++; return( 0 ); } if( ssl->record_read == 0 ) { if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 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" ) ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } ssl->record_read = 1; } ssl->client_auth = 0; ssl->state++; if( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ) ssl->client_auth++; MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", ssl->client_auth ? "a" : "no" ) ); if( ssl->client_auth == 0 ) goto exit; ssl->record_read = 0; // TODO: handshake_failure alert for an anonymous server to request // client authentication /* * 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; */ buf = ssl->in_msg; // Retrieve cert types // cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; n = cert_type_len; if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } p = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 1; while( cert_type_len > 0 ) { #if defined(MBEDTLS_RSA_C) if( *p == MBEDTLS_SSL_CERT_TYPE_RSA_SIGN && mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) { ssl->handshake->cert_type = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; break; } else #endif #if defined(MBEDTLS_ECDSA_C) if( *p == MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN && mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) { ssl->handshake->cert_type = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; break; } else #endif { ; /* Unsupported cert type, ignore */ } cert_type_len--; p++; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { /* Ignored, see comments about hash in write_certificate_verify */ // TODO: should check the signature part against our pk_key though size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); m += 2; n += sig_alg_len; if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* Ignore certificate_authorities, we only have one cert anyway */ // TODO: should not send cert if no CA matches dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + m + n] << 8 ) | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + m + n] ) ); n += dn_len; if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + m + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } exit: MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); return( 0 ); } #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) { int ret; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); if( ssl->record_read == 0 ) { if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 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 ); } } ssl->record_read = 0; 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" ) ); 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; 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 ); return( ret ); } MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); 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( ret ); } MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.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( 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 ) { /* * 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_MAX_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_MAX_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_MAX_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_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.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_MAX_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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", 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_ECDHE_RSA_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; 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 ); } 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 an RSA signature of the handshake digests */ 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( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, ssl->out_msg + 6 + offset, &n, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); 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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", 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_ECDHE_RSA_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 ) ) != 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" ) ); 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" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); } msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); lifetime = ( 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" ) ); 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 ); ssl_cli_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" ) ); 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_resend( ssl ) ) != 0 ) return( ret ); } #endif /* 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 */ /********* Start of file library/ssl_cookie.c ************/ /* * DTLS cookie callbacks implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_SSL_COOKIE_C) #if defined(MBEDTLS_PLATFORM_C) #else #define mbedtls_calloc calloc #define mbedtls_free free #endif #include /* Implementation that should never be optimized out by the compiler */ static void ssl_cookie_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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_init( &ctx->mutex ); #endif ssl_cookie_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 ); ssl_cookie_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) 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) 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 */ /********* Start of file library/ssl_srv.c ************/ /* * SSLv3/TLSv1 server-side functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_SSL_SRV_C) #include #if defined(MBEDTLS_ECP_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #if defined(MBEDTLS_HAVE_TIME) #include #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) /* Implementation that should never be optimized out by the compiler */ static void ssl_srv_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } #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" ) ); servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( servername_list_size + 2 != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } p = buf + 2; while( servername_list_size > 0 ) { hostname_len = ( ( p[1] << 8 ) | p[2] ); if( hostname_len + 3 > servername_list_size ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); 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" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } return( 0 ); } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ static int ssl_srv_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { int ret; #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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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) 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; const int *md_cur; 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" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } /* * For now, ignore the SignatureAlgorithm part and rely on offered * ciphersuites only for that part. To be fixed later. * * So, just look at the HashAlgorithm part. */ for( md_cur = ssl->conf->sig_hashes; *md_cur != MBEDTLS_MD_NONE; md_cur++ ) { for( p = buf + 2; p < end; p += 2 ) { if( *md_cur == (int) mbedtls_ssl_md_alg_from_hash( p[0] ) ) { ssl->handshake->sig_alg = p[0]; goto have_sig_alg; } } } /* Some key echanges do not need signatures at all */ MBEDTLS_SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) ); return( 0 ); have_sig_alg: MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", ssl->handshake->sig_alg ) ); 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; 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" ) ); 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" ) ); 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 ) 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; list_size = buf[0]; if( list_size + 1 != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } 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 ); 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_srv_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" ) ); 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_srv_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" ) ); 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_srv_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" ) ); 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_srv_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" ) ); 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_srv_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 */ ssl_srv_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_srv_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 ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); list_len = ( buf[0] << 8 ) | buf[1]; if( list_len != len - 2 ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); /* * Use our order of preference */ start = buf + 2; end = buf + len; for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) { ours_len = strlen( *ours ); for( theirs = start; theirs != end; theirs += cur_len ) { /* If the list is well formed, we should get equality first */ if( theirs > end ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); cur_len = *theirs++; /* Empty strings MUST NOT be included */ if( cur_len == 0 ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); 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->key, 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->key, 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; 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_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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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; mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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 */ 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; 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 ) { 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->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_MAX_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 ommitted) 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" ) ); 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" ) ); 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 ) { 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" ) ); 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" ) ); 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 /* * 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" ) ); 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" ) ); 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 = ( ( 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 client hello message" ) ); 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_srv_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" ) ); #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) break; #endif ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); if( ret != 0 ) return( ret ); 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_srv_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_srv_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_srv_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_srv_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_srv_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_srv_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" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } } #if defined(MBEDTLS_SSL_FALLBACK_SCSV) for( i = 0, p = buf + 41 + sess_len; 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 */ /* * 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" ) ); if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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 ) { if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); 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_fatal_handshake_failure( ssl ); return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); } else { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); mbedtls_ssl_send_fatal_handshake_failure( ssl ); for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) { int code = (p[0] & 0xFF) << 8 | (p[1] & 0xFF); MBEDTLS_SSL_DEBUG_MSG( 1, ( "Client cipher %s, 0x%04X", mbedtls_ssl_get_ciphersuite_name(code), code)); } 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; mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->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 MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); return( 0 ); } #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) static void ssl_srv_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_srv_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_EXTENDED_MS_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_srv_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_srv_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_srv_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_srv_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_srv_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_srv_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_MAX_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_srv_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_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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } 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) 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 = 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_srv_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 = 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 ) ); /* * First write extensions, then the total length */ ssl_srv_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ssl_srv_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) ssl_srv_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) ssl_srv_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) ssl_srv_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) ssl_srv_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) ssl_srv_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ssl_srv_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif #if defined(MBEDTLS_SSL_ALPN) ssl_srv_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; } 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_record( 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_ECDHE_RSA_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_MAX_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 ) { /* * Only use current running hash algorithm that is already required * for requested ciphersuite. */ ssl->handshake->verify_sig_alg = MBEDTLS_SSL_HASH_SHA256; if( ssl->transform_negotiate->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) { ssl->handshake->verify_sig_alg = MBEDTLS_SSL_HASH_SHA384; } /* * Supported signature algorithms */ #if defined(MBEDTLS_RSA_C) p[2 + sa_len++] = ssl->handshake->verify_sig_alg; p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; #endif #if defined(MBEDTLS_ECDSA_C) p[2 + sa_len++] = ssl->handshake->verify_sig_alg; 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; #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; total_dn_size = 0; 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_record( 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_ECDHE_RSA_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_srv_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 */ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) { int ret; size_t n = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) unsigned char *p = ssl->out_msg + 4; unsigned char *dig_signed = p; size_t dig_signed_len = 0, len; ((void) dig_signed); ((void) dig_signed_len); ((void) len); #endif MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); ssl->state++; return( 0 ); } #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 ) { ssl_srv_get_ecdh_params_from_cert( ssl ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); ssl->state++; return( 0 ); } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) { size_t jlen; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, p, end - p, &jlen, ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); return( ret ); } p += jlen; n += jlen; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #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 ) { /* TODO: Support identity hints */ *(p++) = 0x00; *(p++) = 0x00; n += 2; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_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->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_mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->conf->dhm_P ) ) != 0 || ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->conf->dhm_G ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_mpi_copy", ret ); return( ret ); } if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); return( ret ); } dig_signed = p; dig_signed_len = len; p += len; n += 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_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_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_ECDHE_PSK ) { /* * Ephemeral ECDH parameters: * * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ const mbedtls_ecp_curve_info **curve = NULL; const mbedtls_ecp_group_id *gid; /* 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_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, (*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, p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); return( ret ); } dig_signed = p; dig_signed_len = len; p += len; n += len; MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); } #endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) { size_t signature_len = 0; unsigned int hashlen = 0; unsigned char hash[64]; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; /* * Choose hash algorithm. NONE means MD5 + SHA1 here. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->sig_alg ); if( md_alg == MBEDTLS_MD_NONE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); 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 ) { md_alg = MBEDTLS_MD_SHA1; } else #endif { md_alg = MBEDTLS_MD_NONE; } /* * 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 ) { 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); */ mbedtls_md5_starts( &mbedtls_md5 ); mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len ); mbedtls_md5_finish( &mbedtls_md5, hash ); mbedtls_sha1_starts( &mbedtls_sha1 ); mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); mbedtls_sha1_update( &mbedtls_sha1, dig_signed, dig_signed_len ); mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); hashlen = 36; mbedtls_md5_free( &mbedtls_md5 ); mbedtls_sha1_free( &mbedtls_sha1 ); } 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 ) { mbedtls_md_context_t ctx; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); mbedtls_md_init( &ctx ); /* Info from md_alg will be used instead */ hashlen = 0; /* * 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 ); return( ret ); } mbedtls_md_starts( &ctx ); mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); mbedtls_md_update( &ctx, dig_signed, dig_signed_len ); mbedtls_md_finish( &ctx, hash ); mbedtls_md_free( &ctx ); } 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 != 0 ? hashlen : (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); /* * Make the signature */ if( mbedtls_ssl_own_key( ssl ) == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { *(p++) = ssl->handshake->sig_alg; *(p++) = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); n += 2; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); return( ret ); } *(p++) = (unsigned char)( signature_len >> 8 ); *(p++) = (unsigned char)( signature_len ); n += 2; MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); n += signature_len; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ ssl->out_msglen = 4 + n; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; ssl->state++; if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", 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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } 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) static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, const unsigned char *p, const unsigned char *end, size_t pms_offset ) { int ret; size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); 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; if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); } /* * 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++ != ( ( 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 ); } mbedtls_ssl_write_version( ssl->handshake->max_major_ver, ssl->handshake->max_minor_ver, ssl->conf->transport, ver ); /* * 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. * Also, avoid data-dependant branches here to protect against * timing-based variants. */ ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); if( ret != 0 ) return( ret ); ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, peer_pms, &peer_pmslen, sizeof( peer_pms ), ssl->conf->f_rng, ssl->conf->p_rng ); diff = (unsigned int) ret; diff |= peer_pmslen ^ 48; diff |= peer_pms[0] ^ ver[0]; diff |= peer_pms[1] ^ ver[1]; #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; /* 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 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( *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( n < 1 || n > 65535 || *p + n > end ) { 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 ); if( ( ret = mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 ) { return( ret ); } 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( ( ret = mbedtls_ssl_read_record( ssl ) ) != 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_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.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_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.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( ( 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_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.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_ECDHE_RSA_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 ); } /* Needs to be done before read_record() to exclude current message */ ssl->handshake->calc_verify( ssl, hash ); if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } ssl->state++; 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 */ if( ssl->in_msg[i] != ssl->handshake->verify_sig_alg ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" " for verify message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); } md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->verify_sig_alg ); /* 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 ); } 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_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); return( ret ); } #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_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_MAX_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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", 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_resend( ssl ) ) != 0 ) return( ret ); } #endif 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 */ /********* Start of file library/ssl_ticket.c ************/ /* * TLS server tickets callbacks implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_SSL_TICKET_C) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif #include /* Implementation that should never be optimized out by the compiler */ static void ssl_ticket_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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) 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 ); ssl_ticket_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) 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( p + sizeof( mbedtls_ssl_session ) > end ) 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( p + 3 > end ) 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( p + cert_len > end ) 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 */ time_t current_time = 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 ssl_ticket_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); } #endif /* MBEDTLS_SSL_TICKET_C */ /********* Start of file library/ssl_tls.c ************/ /* * SSLv3/TLSv1 shared functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_SSL_TLS_C) #include #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_calloc calloc #define mbedtls_free free #endif /* Implementation that should never be optimized out by the compiler */ static void ssl_tls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* 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 ); } #if defined(MBEDTLS_SSL_PROTO_DTLS) /* * 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 ); 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 mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = { MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ }; #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 ) { 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 ); mbedtls_sha1_starts( &sha1 ); mbedtls_sha1_update( &sha1, padding, 1 + i ); mbedtls_sha1_update( &sha1, secret, slen ); mbedtls_sha1_update( &sha1, random, rlen ); mbedtls_sha1_finish( &sha1, sha1sum ); mbedtls_md5_starts( &md5 ); mbedtls_md5_update( &md5, secret, slen ); mbedtls_md5_update( &md5, sha1sum, 20 ); mbedtls_md5_finish( &md5, dstbuf + i * 16 ); } mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); ssl_tls_zeroize( padding, sizeof( padding ) ); ssl_tls_zeroize( sha1sum, sizeof( sha1sum ) ); return( 0 ); } #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 ); ssl_tls_zeroize( tmp, sizeof( tmp ) ); ssl_tls_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_(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 ); ssl_tls_zeroize( tmp, sizeof( tmp ) ); ssl_tls_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 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 ); } ssl_tls_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 ); ssl_tls_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 ); ssl_tls_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 ) { transform->maclen = 0; transform->ivlen = 12; transform->fixed_ivlen = 4; /* Minimum length is expicit IV + tag */ transform->minlen = transform->ivlen - transform->fixed_ivlen + ( transform->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); } 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 */ transform->maclen = mbedtls_md_get_size( md_info ); #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; #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 + transform->maclen * 2; key2 = keyblk + transform->maclen * 2 + transform->keylen; mac_enc = keyblk; mac_dec = keyblk + transform->maclen; /* * 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 + transform->maclen * 2 + transform->keylen; key2 = keyblk + transform->maclen * 2; mac_enc = keyblk + transform->maclen; 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( transform->maclen > sizeof transform->mac_enc ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } memcpy( transform->mac_enc, mac_enc, transform->maclen ); memcpy( transform->mac_dec, mac_dec, transform->maclen ); } 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 ) { mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); } 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 ) { int ret = 0; 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, transform->maclen ) ) != 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, transform->maclen, 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 */ ssl_tls_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_BUFFER_LEN ); if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_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( &md5, ssl->session_negotiate->master, 48 ); mbedtls_md5_update( &md5, pad_1, 48 ); mbedtls_md5_finish( &md5, hash ); mbedtls_md5_starts( &md5 ); mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); mbedtls_md5_update( &md5, pad_2, 48 ); mbedtls_md5_update( &md5, hash, 16 ); mbedtls_md5_finish( &md5, hash ); mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); mbedtls_sha1_update( &sha1, pad_1, 40 ); mbedtls_sha1_finish( &sha1, hash + 16 ); mbedtls_sha1_starts( &sha1 ); mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); mbedtls_sha1_update( &sha1, pad_2, 40 ); mbedtls_sha1_update( &sha1, hash + 16, 20 ); mbedtls_sha1_finish( &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( &md5, hash ); mbedtls_sha1_finish( &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( &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( &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 */ *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_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.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 */ static void ssl_mac( mbedtls_md_context_t *md_ctx, unsigned char *secret, unsigned char *buf, size_t len, unsigned char *ctr, int type ) { 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, buf + len ); 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, buf + len, md_size ); mbedtls_md_finish( md_ctx, buf + len ); } #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) ) ) #define SSL_SOME_MODES_USE_MAC #endif /* * 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 ) { 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 ); } 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 ) { 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, ssl->out_msg + ssl->out_msglen ); mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); } 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) if( mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM ) { int ret; size_t enc_msglen, olen; unsigned char *enc_msg; unsigned char add_data[13]; unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; 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 used for AEAD", add_data, 13 ); /* * Generate IV */ #if defined(MBEDTLS_SSL_AEAD_RANDOM_IV) ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); if( ret != 0 ) return( ret ); memcpy( ssl->out_iv, ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); #else if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) { /* 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 ); } memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, ssl->out_ctr, 8 ); memcpy( ssl->out_iv, ssl->out_ctr, 8 ); #endif MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, ssl->transform_out->ivlen - ssl->transform_out->fixed_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 - ssl->transform_out->fixed_ivlen; MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " "including %d bytes of padding", ssl->out_msglen, 0 ) ); /* * Encrypt and authenticate */ if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, ssl->transform_out->iv_enc, ssl->transform_out->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) ) 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 ) { /* * 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, ssl->out_iv + ssl->out_msglen ); mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); 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_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 ); } #define SSL_MAX_MAC_SIZE 48 static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { size_t i; 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) if( mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM ) { int ret; size_t dec_msglen, olen; unsigned char *dec_msg; unsigned char *dec_msg_result; unsigned char add_data[13]; unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; size_t explicit_iv_len = ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen; 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; 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 used for AEAD", add_data, 13 ); memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, ssl->in_iv, ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, ssl->transform_in->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, ssl->transform_in->iv_dec, ssl->transform_in->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) ) 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 computed_mac[SSL_MAX_MAC_SIZE]; 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, computed_mac ); 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, "computed mac", computed_mac, ssl->transform_in->maclen ); if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac, 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 ) { 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 - 1; /* * Padding is guaranteed to be incorrect if: * 1. padlen >= ssl->in_msglen * * 2. padding_idx >= MBEDTLS_SSL_MAX_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 &= ( ssl->in_msglen >= padlen + 1 ); correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + ssl->transform_in->maclen ); padding_idx *= correct; for( i = 1; 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_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", ssl->in_msg, ssl->in_msglen ); /* * 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 tmp[SSL_MAX_MAC_SIZE]; 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 ); memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); #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 ); } 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 * * extra_run compensates MAC check for padlen * * Known timing attacks: * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) * * 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) */ size_t j, extra_run = 0; extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - ( 13 + ssl->in_msglen + 8 ) / 64; 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 ); mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, ssl->in_msg + ssl->in_msglen ); /* Call mbedtls_md_process at least once due to cache attacks */ 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 ); } 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( 4, "message mac", tmp, ssl->transform_in->maclen ); MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); if( mbedtls_ssl_safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, 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 ) { 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 { 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; 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_BUFFER_LEN; 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_BUFFER_LEN - ssl->transform_out->ctx_deflate.avail_out; 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; 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_MAX_CONTENT_LEN; 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_MAX_CONTENT_LEN - ssl->transform_in->ctx_inflate.avail_out; 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_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 accross 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 ) ret = MBEDTLS_ERR_SSL_TIMEOUT; else { len = MBEDTLS_SSL_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 ); 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, i; 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 + mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen - 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 ); ssl->out_left -= ret; } for( i = 8; i > ssl_ep_len( ssl ); i-- ) if( ++ssl->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 ); } 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; /* 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; } 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 void ssl_swap_epochs( mbedtls_ssl_context *ssl ) { mbedtls_ssl_transform *tmp_transform; unsigned char tmp_out_ctr[8]; if( ssl->transform_out == ssl->handshake->alt_transform_out ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); return; } 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->out_ctr, 8 ); memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); /* Adjust to the newly activated transform */ if( ssl->transform_out != NULL && ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) { ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen; } else ssl->out_msg = ssl->out_iv; #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 } /* * 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_resend( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); ssl->handshake->cur_msg = ssl->handshake->flight; ssl_swap_epochs( ssl ); ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; } while( ssl->handshake->cur_msg != NULL ) { int ret; mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; /* 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( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) { ssl_swap_epochs( ssl ); } memcpy( ssl->out_msg, cur->p, cur->len ); ssl->out_msglen = cur->len; ssl->out_msgtype = cur->type; ssl->handshake->cur_msg = cur->next; MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } } 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_resend" ) ); 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; /* 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 */ /* * Record layer functions */ /* * Write current record. * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. */ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) { int ret, done = 0; size_t len = ssl->out_msglen; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); #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 ) { ; /* Skip special handshake treatment when resending */ } else #endif if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) { if( ssl->out_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST && ssl->handshake == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); /* * 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 */ memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); ssl->out_msglen += 8; len += 8; /* Write message_seq and update it, except for HelloRequest */ if( ssl->out_msg[0] != 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; } /* We don't fragment, so frag_offset = 0 and frag_len = len */ memset( ssl->out_msg + 6, 0x00, 3 ); memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ if( ssl->out_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ) ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); } /* Save handshake and CCS messages for resending */ #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 && ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) { if( ( ret = ssl_flight_append( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); return( ret ); } } #endif #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 ) { 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 ); 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 ); } ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; 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], ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); } if( ( 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) /* * 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 ); } /* * Reassemble fragmented DTLS handshake messages. * * Use a temporary buffer for reassembly, divided in two parts: * - the first holds the reassembled message (including handshake header), * - the second holds a bitmask indicating which parts of the message * (excluding headers) have been received so far. */ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) { unsigned char *msg, *bitmask; size_t frag_len, frag_off; size_t msg_len = ssl->in_hslen - 12; /* Without headers */ if( ssl->handshake == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); } /* * For first fragment, check size and allocate buffer */ if( ssl->handshake->hs_msg == NULL ) { size_t alloc_len; MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", msg_len ) ); if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); } /* The bitmask needs one bit per byte of message excluding header */ alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); if( ssl->handshake->hs_msg == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } /* Prepare final header: copy msg_type, length and message_seq, * then add standardised fragment_offset and fragment_length */ memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); memset( ssl->handshake->hs_msg + 6, 0, 3 ); memcpy( ssl->handshake->hs_msg + 9, ssl->handshake->hs_msg + 1, 3 ); } else { /* Make sure msg_type and length are consistent */ if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } } msg = ssl->handshake->hs_msg + 12; bitmask = msg + msg_len; /* * Check and copy current fragment */ frag_off = ( ssl->in_msg[6] << 16 ) | ( ssl->in_msg[7] << 8 ) | ssl->in_msg[8]; frag_len = ( ssl->in_msg[9] << 16 ) | ( ssl->in_msg[10] << 8 ) | ssl->in_msg[11]; if( frag_off + frag_len > msg_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", frag_off, frag_len, msg_len ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } if( frag_len + 12 > ssl->in_msglen ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", frag_len, ssl->in_msglen ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } 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 ); ssl_bitmask_set( bitmask, frag_off, frag_len ); /* * Do we have the complete message by now? * If yes, finalize it, else ask to read the next record. */ if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); return( MBEDTLS_ERR_SSL_WANT_READ ); } MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); if( frag_len + 12 < ssl->in_msglen ) { /* * We'got more handshake messages in the same record. * This case is not handled now because no know implementation does * that and it's hard to test, so we prefer to fail cleanly for now. */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); } if( ssl->in_left > ssl->next_record_offset ) { /* * We've got more data in the buffer after the current record, * that we don't want to overwrite. Move it before writing the * reassembled message, and adjust in_left and next_record_offset. */ unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; size_t remain_len = ssl->in_left - ssl->next_record_offset; /* First compute and check new lengths */ ssl->next_record_offset = new_remain - ssl->in_hdr; ssl->in_left = ssl->next_record_offset + remain_len; if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); } memmove( new_remain, cur_remain, remain_len ); } memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); mbedtls_free( ssl->handshake->hs_msg ); ssl->handshake->hs_msg = NULL; MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", ssl->in_msg, ssl->in_hslen ); return( 0 ); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ static int 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->in_msg[1] << 16 ) | ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3] ); 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]; /* ssl->handshake is NULL when receiving ClientHello for renego */ if( ssl->handshake != NULL && recv_msg_seq != ssl->handshake->in_msg_seq ) { /* 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_WANT_READ ); } /* Wait until message completion to increment in_msg_seq */ /* Reassemble if current message is fragmented or reassembly is * already in progress */ 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 || ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); return( ret ); } } } 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 ); } if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && ssl->handshake != 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 ) { ssl->handshake->in_msg_seq++; } #endif return( 0 ); } /* * 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_MAX_CONTENT_LEN, &len ); MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) { /* Dont 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. */ (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); } if( ret == 0 ) { /* Got a valid cookie, partially reset 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 ret; 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( ( ret = mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) { return( ret ); } 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_BUFFER_LEN - (size_t)( ssl->in_msg - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } /* 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_MAX_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_MAX_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_MAX_CONTENT_LEN + 256 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } #endif } /* * DTLS-related tests done last, because most of them may result in * silently dropping the record (but not the whole datagram), and we only * want to consider that after ensuring that the "basic" fields (type, * version, length) are sane. */ #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]; /* Drop unexpected ChangeCipherSpec messages */ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); } /* 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 ); } /* 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 */ 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 } #endif /* MBEDTLS_SSL_PROTO_DTLS */ 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_MAX_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 ); } // TODO: what's the purpose of these lines? is in_len used? ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); } #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. * */ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) { int ret; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); if( ssl->in_hslen != 0 && ssl->in_hslen < ssl->in_msglen ) { /* * Get next Handshake message in the current record */ 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 ); if( ( ret = ssl_prepare_handshake_record( ssl ) ) != 0 ) return( ret ); return( 0 ); } ssl->in_hslen = 0; /* * Read the record header and parse it */ read_record_header: 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_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 */ goto read_record_header; } #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 ); 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 MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); goto read_record_header; } 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 ); } } /* * When we sent the last flight of the handshake, we MUST respond to a * retransmit of the peer's previous flight with a retransmit. (In * practice, only the Finished message will make it, other messages * including CCS use the old transform so they're dropped as invalid.) * * If the record we received is not a handshake message, however, it * means the peer received our last flight so we can clean up * handshake info. * * This check needs to be done before prepare_handshake() due to an edge * case: if the client immediately requests renegotiation, this * finishes the current handshake first, avoiding the new ClientHello * being mistaken for an ancient message in the current handshake. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL && ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) { if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); return( ret ); } return( MBEDTLS_ERR_SSL_WANT_READ ); } else { ssl_handshake_wrapup_free_hs_transform( ssl ); } } #endif /* * Handle particular types of records */ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) { if( ( ret = ssl_prepare_handshake_record( ssl ) ) != 0 ) return( ret ); } if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) { 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_cert" ) ); /* 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 */ goto read_record_header; } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); 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" ) ); 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 ) ) != 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) 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 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_MAX_CONTENT_LEN - 3 - i ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", i + 3 + n, MBEDTLS_SSL_MAX_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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); return( ret ); } int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t i, n; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; int authmode = ssl->conf->authmode; 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 defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) authmode = ssl->handshake->sni_authmode; #endif 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( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } ssl->state++; #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" ) ); ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) return( 0 ); else 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" ) ); ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) return( 0 ); else 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" ) ); 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" ) ); 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" ) ); 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 ) ) ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); i += 3; while( i < ssl->in_hslen ) { if( ssl->in_msg[i] != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); 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" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, ssl->in_msg + i, n ); if( ret != 0 ) { 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" ) ); 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" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } } #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ 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; } if( ca_chain == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); return( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ); } /* * Main check: verify certificate */ ret = mbedtls_x509_crt_verify_with_profile( 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 ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); } /* * 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 ) { 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; } if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) ret = 0; } 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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", 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 ) ) != 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" ) ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); } /* * 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" ) ); return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset( ssl->in_ctr, 0, 8 ); /* * Set the in_msg pointer to the correct location based on IV length */ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) { ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - ssl->transform_negotiate->fixed_ivlen; } else ssl->in_msg = ssl->in_iv; #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 ); 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( &ssl->handshake->fin_md5 ); mbedtls_sha1_starts( &ssl->handshake->fin_sha1 ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) mbedtls_sha256_starts( &ssl->handshake->fin_sha256, 0 ); #endif #if defined(MBEDTLS_SHA512_C) mbedtls_sha512_starts( &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( &ssl->handshake->fin_md5 , buf, len ); mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); #endif #if defined(MBEDTLS_SHA512_C) mbedtls_sha512_update( &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( &ssl->handshake->fin_md5 , buf, len ); mbedtls_sha1_update( &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( &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( &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( &md5, (const unsigned char *) sender, 4 ); mbedtls_md5_update( &md5, session->master, 48 ); mbedtls_md5_update( &md5, padbuf, 48 ); mbedtls_md5_finish( &md5, md5sum ); mbedtls_sha1_update( &sha1, (const unsigned char *) sender, 4 ); mbedtls_sha1_update( &sha1, session->master, 48 ); mbedtls_sha1_update( &sha1, padbuf, 40 ); mbedtls_sha1_finish( &sha1, sha1sum ); memset( padbuf, 0x5C, 48 ); mbedtls_md5_starts( &md5 ); mbedtls_md5_update( &md5, session->master, 48 ); mbedtls_md5_update( &md5, padbuf, 48 ); mbedtls_md5_update( &md5, md5sum, 16 ); mbedtls_md5_finish( &md5, buf ); mbedtls_sha1_starts( &sha1 ); mbedtls_sha1_update( &sha1, session->master, 48 ); mbedtls_sha1_update( &sha1, padbuf , 40 ); mbedtls_sha1_update( &sha1, sha1sum, 20 ); mbedtls_sha1_finish( &sha1, buf + 16 ); MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); ssl_tls_zeroize( padbuf, sizeof( padbuf ) ); ssl_tls_zeroize( md5sum, sizeof( md5sum ) ); ssl_tls_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( &md5, padbuf ); mbedtls_sha1_finish( &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 ); ssl_tls_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( &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 ); ssl_tls_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( &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 ); ssl_tls_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->handshake ); 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" ) ); /* * Set the out_msg pointer to the correct location based on IV length */ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) { ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - ssl->transform_negotiate->fixed_ivlen; } else ssl->out_msg = ssl->out_iv; ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) 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->out_ctr, 8 ); /* Set sequence_number to zero */ memset( ssl->out_ctr + 2, 0, 6 ); /* Increment epoch */ for( i = 2; i > 0; i-- ) if( ++ssl->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->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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } 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 ) ) != 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" ) ); 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" ) ); 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" ) ); 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( &handshake->fin_md5 ); mbedtls_sha1_starts( &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( &handshake->fin_sha256, 0 ); #endif #if defined(MBEDTLS_SHA512_C) mbedtls_sha512_init( &handshake->fin_sha512 ); mbedtls_sha512_starts( &handshake->fin_sha512, 1 ); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ handshake->update_checksum = ssl_update_checksum_start; handshake->sig_alg = MBEDTLS_SSL_HASH_SHA1; #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_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->handshake ); /* * 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 */ /* * Initialize an SSL context */ void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) { memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); } /* * Setup an SSL context */ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf ) { int ret; const size_t len = MBEDTLS_SSL_BUFFER_LEN; ssl->conf = conf; /* * Prepare base structures */ if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); mbedtls_free( ssl->in_buf ); ssl->in_buf = NULL; return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } #if defined(MBEDTLS_SSL_PROTO_DTLS) if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { ssl->out_hdr = ssl->out_buf; ssl->out_ctr = ssl->out_buf + 3; ssl->out_len = ssl->out_buf + 11; ssl->out_iv = ssl->out_buf + 13; ssl->out_msg = ssl->out_buf + 13; ssl->in_hdr = ssl->in_buf; ssl->in_ctr = ssl->in_buf + 3; ssl->in_len = ssl->in_buf + 11; ssl->in_iv = ssl->in_buf + 13; ssl->in_msg = ssl->in_buf + 13; } else #endif { ssl->out_ctr = ssl->out_buf; ssl->out_hdr = ssl->out_buf + 8; ssl->out_len = ssl->out_buf + 11; ssl->out_iv = ssl->out_buf + 13; ssl->out_msg = ssl->out_buf + 13; ssl->in_ctr = ssl->in_buf; ssl->in_hdr = ssl->in_buf + 8; ssl->in_len = ssl->in_buf + 11; ssl->in_iv = ssl->in_buf + 13; ssl->in_msg = ssl->in_buf + 13; } 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. * * 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; 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->in_msg = ssl->in_buf + 13; ssl->in_msgtype = 0; ssl->in_msglen = 0; if( partial == 0 ) ssl->in_left = 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->record_read = 0; ssl->out_msg = ssl->out_buf + 13; 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 ssl->transform_in = NULL; ssl->transform_out = NULL; memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); if( partial == 0 ) memset( ssl->in_buf, 0, MBEDTLS_SSL_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( partial == 0 ) { 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_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, int (*f_send)(void *, const unsigned char *, size_t), int (*f_recv)(void *, unsigned char *, size_t), int (*f_recv_timeout)(void *, unsigned char *, size_t, uint32_t) ) { ssl->p_bio = p_bio; ssl->f_send = f_send; ssl->f_recv = f_recv; ssl->f_recv_timeout = f_recv_timeout; } 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, void (*f_set_timer)(void *, uint32_t int_ms, uint32_t fin_ms), int (*f_get_timer)(void *) ) { 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; new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); if( new == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); new->cert = cert; new->key = key; new->next = NULL; /* Update head is the list was null, else add to the end */ if( *head == NULL ) { *head = new; } else { mbedtls_ssl_key_cert *cur = *head; while( cur->next != NULL ) cur = cur->next; cur->next = new; } 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_MAX_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } if( conf->psk != NULL || conf->psk_identity != NULL ) { mbedtls_free( conf->psk ); mbedtls_free( conf->psk_identity ); conf->psk = NULL; conf->psk_identity = NULL; } 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_free( ssl->handshake->psk ); 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) 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 ); } 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 #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 #if defined(MBEDTLS_X509_CRT_PARSE_C) int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) { size_t hostname_len; if( hostname == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); hostname_len = strlen( hostname ); if( hostname_len + 1 == 0 ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 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 #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; /* * "Empty strings MUST NOT be included and byte strings MUST NOT be * truncated". 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_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 || mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_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 /* * SSL get accessors */ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) { return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); } 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; const mbedtls_ssl_transform *transform = ssl->transform_out; #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); #endif if( transform == NULL ) return( (int) mbedtls_ssl_hdr_len( ssl ) ); switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) { case MBEDTLS_MODE_GCM: case MBEDTLS_MODE_CCM: case MBEDTLS_MODE_STREAM: transform_expansion = transform->minlen; break; case MBEDTLS_MODE_CBC: transform_expansion = transform->maclen + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); 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 = mfl_code_to_length[ssl->conf->mfl_code]; /* * Check if a smaller max length was negotiated */ if( ssl->session_out != NULL && mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) { max_len = mfl_code_to_length[ssl->session_out->mfl_code]; } return max_len; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #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_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", 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 ) { if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) { return( 0 ); } if( memcmp( ssl->in_ctr, ssl->conf->renego_period, 8 ) <= 0 && memcmp( ssl->out_ctr, ssl->conf->renego_period, 8 ) <= 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, record_read = 0; 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_resend( ssl ) ) != 0 ) return( ret ); } } #endif #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 ) { ret = mbedtls_ssl_handshake( ssl ); if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) { record_read = 1; } else if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); return( ret ); } } if( 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( ! record_read ) { if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 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 ) ) != 0 ) { if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) return( 0 ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } } #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); #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 ) return( MBEDTLS_ERR_SSL_WANT_READ ); #endif return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } 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 ) return( MBEDTLS_ERR_SSL_WANT_READ ); #endif return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } #endif 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 ) ) { 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" alert */ if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) return( ret ); } 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 ); } } else { /* 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 ) { record_read = 1; } else if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); return( ret ); } } /* If a non-handshake record was read during renego, fallthrough, * else tell the user they should call mbedtls_ssl_read() again */ if( ! record_read ) return( MBEDTLS_ERR_SSL_WANT_READ ); } 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 } 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; 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 */ static int ssl_write_real( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { int ret; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); 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; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ if( ssl->out_left != 0 ) { if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); return( ret ); } } else { 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 ) ) != 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 wether 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 ); ssl_tls_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 */ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) { if( handshake == NULL ) return; #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) /* 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 ) { ssl_tls_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_PROTO_DTLS) mbedtls_free( handshake->verify_cookie ); mbedtls_free( handshake->hs_msg ); ssl_flight_free( handshake->flight ); #endif ssl_tls_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 ssl_tls_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 ) { ssl_tls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); mbedtls_free( ssl->out_buf ); } if( ssl->in_buf != NULL ) { ssl_tls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); mbedtls_free( ssl->in_buf ); } #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->compress_buf != NULL ) { ssl_tls_zeroize( ssl->compress_buf, MBEDTLS_SSL_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->handshake ); 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 ) { ssl_tls_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 */ ssl_tls_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) 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[] = { MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_SECP384R1, 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_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, 0xFF, 7 ); conf->renego_period[7] = 0x00; #endif #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) if( endpoint == MBEDTLS_SSL_IS_SERVER ) { if( ( ret = mbedtls_ssl_conf_dh_param( conf, MBEDTLS_DHM_RFC5114_MODP_2048_P, MBEDTLS_DHM_RFC5114_MODP_2048_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_MAJOR_VERSION_3; conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_1; /* TLS 1.0 */ 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 ) { ssl_tls_zeroize( conf->psk, conf->psk_len ); ssl_tls_zeroize( conf->psk_identity, conf->psk_identity_len ); mbedtls_free( conf->psk ); mbedtls_free( conf->psk_identity ); conf->psk_len = 0; conf->psk_identity_len = 0; } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) ssl_key_cert_free( conf->key_cert ); #endif ssl_tls_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 ); } 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 ) */ /* * 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 one 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]; } } #endif /* MBEDTLS_SSL_TLS_C */ /********* Start of file library/threading.c ************/ /* * Threading abstraction layer * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_THREADING_C) #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 ) return; (void) pthread_mutex_destroy( &mutex->mutex ); } 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; mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); } /* * Free global mutexes */ void mbedtls_threading_free_alt( void ) { mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); } #endif /* MBEDTLS_THREADING_ALT */ /* * Define global mutexes */ #ifndef MUTEX_INIT #define MUTEX_INIT #endif mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; #endif /* MBEDTLS_THREADING_C */ /********* Start of file library/timing.c ************/ /* * Portable interface to the CPU cycle counter * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif #if defined(MBEDTLS_TIMING_C) #if !defined(MBEDTLS_TIMING_ALT) #ifndef asm #define asm __asm #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #include struct _hr_time { LARGE_INTEGER start; }; #else #include #include #if !VXWORKS #include #endif #include #include 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 ) { unsigned long delta; LARGE_INTEGER offset, hfreq; struct _hr_time *t = (struct _hr_time *) val; QueryPerformanceCounter( &offset ); QueryPerformanceFrequency( &hfreq ); delta = (unsigned long)( ( 1000 * ( offset.QuadPart - t->start.QuadPart ) ) / hfreq.QuadPart ); if( reset ) QueryPerformanceCounter( &t->start ); return( delta ); } /* It's OK to use a global because alarm() is supposed to be global anyway */ static DWORD alarmMs; static DWORD WINAPI TimerProc( LPVOID TimerContext ) { ((void) TimerContext); Sleep( alarmMs ); mbedtls_timing_alarmed = 1; return( TRUE ); } void mbedtls_set_alarm( int seconds ) { DWORD ThreadId; mbedtls_timing_alarmed = 0; alarmMs = seconds * 1000; CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); } #else /* _WIN32 && !EFIX64 && !EFI32 */ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) { unsigned long delta; struct timeval offset; struct _hr_time *t = (struct _hr_time *) val; gettimeofday( &offset, NULL ); if( reset ) { t->start.tv_sec = offset.tv_sec; t->start.tv_usec = offset.tv_usec; return( 0 ); } delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 + ( offset.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 ); alarm( seconds ); } #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\n" ); \ \ 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, ratio; unsigned long millisecs, secs; int hardfail; struct mbedtls_timing_hr_time hires; uint32_t a, b; 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): " ); for( secs = 1; secs <= 3; secs++ ) { (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 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } } if( verbose != 0 ) mbedtls_printf( "passed\n" ); if( verbose != 0 ) mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); for( a = 200; a <= 400; a += 200 ) { for( b = 200; b <= 400; b += 200 ) { mbedtls_timing_set_delay( &ctx, a, a + b ); busy_msleep( a - a / 8 ); if( mbedtls_timing_get_delay( &ctx ) != 0 ) FAIL; busy_msleep( a / 4 ); if( mbedtls_timing_get_delay( &ctx ) != 1 ) FAIL; busy_msleep( b - a / 8 - b / 8 ); if( mbedtls_timing_get_delay( &ctx ) != 1 ) FAIL; busy_msleep( 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. */ hardfail = 0; 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 */ /********* Start of file library/version.c ************/ /* * Version information * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_VERSION_C) #include unsigned int mbedtls_version_get_number() { 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 */ /********* Start of file library/version_features.c ************/ /* * Version feature information * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_VERSION_C) #include static const char *features[] = { #if defined(MBEDTLS_VERSION_FEATURES) #if defined(MBEDTLS_HAVE_ASM) "MBEDTLS_HAVE_ASM", #endif /* MBEDTLS_HAVE_ASM */ #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_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_DEPRECATED_WARNING) "MBEDTLS_DEPRECATED_WARNING", #endif /* MBEDTLS_DEPRECATED_WARNING */ #if defined(MBEDTLS_DEPRECATED_REMOVED) "MBEDTLS_DEPRECATED_REMOVED", #endif /* MBEDTLS_DEPRECATED_REMOVED */ #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_BLOWFISH_ALT) "MBEDTLS_BLOWFISH_ALT", #endif /* MBEDTLS_BLOWFISH_ALT */ #if defined(MBEDTLS_CAMELLIA_ALT) "MBEDTLS_CAMELLIA_ALT", #endif /* MBEDTLS_CAMELLIA_ALT */ #if defined(MBEDTLS_DES_ALT) "MBEDTLS_DES_ALT", #endif /* MBEDTLS_DES_ALT */ #if defined(MBEDTLS_XTEA_ALT) "MBEDTLS_XTEA_ALT", #endif /* MBEDTLS_XTEA_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_RIPEMD160_ALT) "MBEDTLS_RIPEMD160_ALT", #endif /* MBEDTLS_RIPEMD160_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_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_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_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_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_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_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_NIST_OPTIM) "MBEDTLS_ECP_NIST_OPTIM", #endif /* MBEDTLS_ECP_NIST_OPTIM */ #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_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_AEAD_RANDOM_IV) "MBEDTLS_SSL_AEAD_RANDOM_IV", #endif /* MBEDTLS_SSL_AEAD_RANDOM_IV */ #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) "MBEDTLS_SSL_ALL_ALERT_MESSAGES", #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ #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_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_CCM_C) "MBEDTLS_CCM_C", #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CERTS_C) "MBEDTLS_CERTS_C", #endif /* MBEDTLS_CERTS_C */ #if defined(MBEDTLS_CIPHER_C) "MBEDTLS_CIPHER_C", #endif /* MBEDTLS_CIPHER_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_HMAC_DRBG_C) "MBEDTLS_HMAC_DRBG_C", #endif /* MBEDTLS_HMAC_DRBG_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_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 */ /********* Start of file library/x509.c ************/ /* * X.509 common functions for parsing and verification * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_X509_USE_C) #include #include #if defined(MBEDTLS_PEM_PARSE_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #include #define mbedtls_free free #define mbedtls_calloc calloc #define mbedtls_printf printf #define mbedtls_snprintf snprintf #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #else #include #endif #if defined(MBEDTLS_FS_IO) #include #if !defined(_WIN32) #include #include #include #endif #endif #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } /* * 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) paramaters */ 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 ); 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; 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, unsigned 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; } /* * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } */ int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, mbedtls_x509_time *time ) { int ret; size_t 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 ) { (*p)++; ret = mbedtls_asn1_get_len( p, end, &len ); if( ret != 0 ) return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); CHECK( x509_parse_int( p, 2, &time->year ) ); CHECK( x509_parse_int( p, 2, &time->mon ) ); CHECK( x509_parse_int( p, 2, &time->day ) ); CHECK( x509_parse_int( p, 2, &time->hour ) ); CHECK( x509_parse_int( p, 2, &time->min ) ); if( len > 10 ) CHECK( x509_parse_int( p, 2, &time->sec ) ); if( len > 12 && *(*p)++ != 'Z' ) return( MBEDTLS_ERR_X509_INVALID_DATE ); time->year += 100 * ( time->year < 50 ); time->year += 1900; return( 0 ); } else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) { (*p)++; ret = mbedtls_asn1_get_len( p, end, &len ); if( ret != 0 ) return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); CHECK( x509_parse_int( p, 4, &time->year ) ); CHECK( x509_parse_int( p, 2, &time->mon ) ); CHECK( x509_parse_int( p, 2, &time->day ) ); CHECK( x509_parse_int( p, 2, &time->hour ) ); CHECK( x509_parse_int( p, 2, &time->min ) ); if( len > 12 ) CHECK( x509_parse_int( p, 2, &time->sec ) ); if( len > 14 && *(*p)++ != 'Z' ) return( MBEDTLS_ERR_X509_INVALID_DATE ); return( 0 ); } else return( MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); } int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) { int ret; size_t len; if( ( end - *p ) < 1 ) return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); sig->tag = **p; if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); 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; if( *p == end ) return( 0 ); ext->tag = **p; if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) return( ret ); ext->p = *p; end = *p + ext->len; /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension * * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING } */ 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. */ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) static int x509_get_current_time( mbedtls_x509_time *now ) { SYSTEMTIME st; GetSystemTime( &st ); now->year = st.wYear; now->mon = st.wMonth; now->day = st.wDay; now->hour = st.wHour; now->min = st.wMinute; now->sec = st.wSecond; return( 0 ); } #else static int x509_get_current_time( mbedtls_x509_time *now ) { struct tm *lt; time_t tt; int ret = 0; #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif tt = time( NULL ); lt = gmtime( &tt ); 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; } #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif return( ret ); } #endif /* _WIN32 && !EFIX64 && !EFI32 */ /* * 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) /* * Checkup routine */ int mbedtls_x509_self_test( int verbose ) { #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA1_C) int ret; uint32_t flags; mbedtls_x509_crt cacert; mbedtls_x509_crt clicert; if( verbose != 0 ) mbedtls_printf( " X.509 certificate load: " ); 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" ); return( ret ); } mbedtls_x509_crt_init( &cacert ); 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" ); return( ret ); } 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" ); return( ret ); } if( verbose != 0 ) mbedtls_printf( "passed\n\n"); mbedtls_x509_crt_free( &cacert ); mbedtls_x509_crt_free( &clicert ); return( 0 ); #else ((void) verbose); return( 0 ); #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ } #endif /* MBEDTLS_SELF_TEST */ /* Amalgamated Release Mappings */ #undef SAFE_SNPRINTF #endif /* MBEDTLS_X509_USE_C */ /********* Start of file library/x509_create.c ************/ /* * X.509 base functions for creating certificates / CSRs * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_X509_CREATE_C) #include typedef struct { const char *name; size_t name_len; const char*oid; } x509_attr_descriptor_t; #define ADD_STRLEN( s ) s, sizeof( s ) - 1 static const x509_attr_descriptor_t x509_attrs[] = { { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, { NULL, 0, NULL } }; static const char *x509_at_oid_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; return( cur->oid ); } 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; 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( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) { ret = MBEDTLS_ERR_X509_UNKNOWN_OID; goto exit; } 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 ) ) { if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), (unsigned char *) data, d - data ) == NULL ) { return( MBEDTLS_ERR_X509_ALLOC_FAILED ); } 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, const char *oid, size_t oid_len, const unsigned char *name, size_t name_len ) { int ret; size_t len = 0; // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL // if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 ) { MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start, (const char *) name, name_len ) ); } else { MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start, (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, (char *) cur->oid.p, cur->oid.len, cur->val.p, cur->val.len ) ); 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 */ /********* Start of file library/x509_crl.c ************/ /* * X.509 Certidicate Revocation List (CRL) parsing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_X509_CRL_PARSE_C) #include #if defined(MBEDTLS_PEM_PARSE_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #include #define mbedtls_free free #define mbedtls_calloc calloc #define mbedtls_snprintf snprintf #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #else #include #endif #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) #include #endif /* Implementation that should never be optimized out by the compiler */ static void x509_crl_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 (no extensions parsed yet.) */ static int x509_get_crl_ext( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext ) { int ret; size_t len = 0; /* Get explicit tag */ if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 ) { if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) return( 0 ); return( ret ); } 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 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, *end; 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( ( p = mbedtls_calloc( 1, buflen ) ) == 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 ); } crl->version++; if( crl->version > 2 ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_UNKNOWN_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 ) { return( ret ); } mbedtls_pem_free( &pem ); } else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) { mbedtls_pem_free( &pem ); return( ret ); } } /* 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 ); x509_crl_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; x509_crl_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; x509_crl_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); mbedtls_free( entry_prv ); } if( crl_cur->raw.p != NULL ) { x509_crl_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; x509_crl_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); if( crl_prv != crl ) mbedtls_free( crl_prv ); } while( crl_cur != NULL ); } /* Amalgamated Release Mappings */ #undef SAFE_SNPRINTF #undef BEFORE_COLON #undef BC #endif /* MBEDTLS_X509_CRL_PARSE_C */ /********* Start of file library/x509_crt.c ************/ /* * X.509 certificate parsing and verification * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #include #include #if defined(MBEDTLS_PEM_PARSE_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_free free #define mbedtls_calloc calloc #define mbedtls_snprintf snprintf #endif #if defined(MBEDTLS_THREADING_C) #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #else #include #endif #if defined(MBEDTLS_FS_IO) #include #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) #include #include #include #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif /* Implementation that should never be optimized out by the compiler */ static void x509_crt_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * Default profile */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { /* Hashes from SHA-1 and above */ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) | 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 ), #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 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( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) return( 0 ); return( -1 ); } /* * Check pk_alg against profile * Return 0 if pk_alg 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( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) return( 0 ); return( -1 ); } /* * Check key against profile * Return 0 if pk_alg acceptable for this profile, -1 otherwise */ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, mbedtls_pk_type_t pk_alg, const mbedtls_pk_context *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 ) { mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) return( 0 ); return( -1 ); } #endif return( -1 ); } /* * 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( 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( 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_CONTEXT_SPECIFIC ) != 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 * * TODO: Perform all of the basic constraints tests required by the RFC * TODO: Set values for undetected extensions to a sane default? * */ 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( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) { if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) return( 0 ); return( ret ); } 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 */ extn_oid.tag = **p; if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); extn_oid.p = *p; *p += extn_oid.len; if( ( end - *p ) < 1 ) return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); /* 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 ); p = mbedtls_calloc( 1, len = buflen ); if( p == NULL ) return( MBEDTLS_ERR_X509_ALLOC_FAILED ); memcpy( p, buf, buflen ); crt->raw.p = p; crt->raw.len = len; 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; /* * 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 ); } crt->version++; if( crt->version > 3 ) { mbedtls_x509_crt_free( crt ); return( MBEDTLS_ERR_X509_UNKNOWN_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 ) { int success = 0, first_error = 0, total_failed = 0; int buf_format = MBEDTLS_X509_FORMAT_DER; /* * 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; } #endif if( buf_format == MBEDTLS_X509_FORMAT_DER ) return mbedtls_x509_crt_parse_der( chain, buf, buflen ); #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; } } #endif /* MBEDTLS_PEM_PARSE_C */ if( success ) return( total_failed ); else if( first_error ) return( first_error ); else return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); } #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 ); x509_crt_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, 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 ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); 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; FindClose( hFind ); #else /* _WIN32 */ int t_ret; struct stat sb; struct dirent *entry; char entry_name[255]; DIR *dir = opendir( path ); if( dir == NULL ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); #if defined(MBEDTLS_THREADING_PTHREAD) if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) { closedir( dir ); return( ret ); } #endif while( ( entry = readdir( dir ) ) != NULL ) { mbedtls_snprintf( entry_name, sizeof entry_name, "%s/%s", path, entry->d_name ); if( stat( entry_name, &sb ) == -1 ) { closedir( dir ); 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; } closedir( dir ); cleanup: #if defined(MBEDTLS_THREADING_PTHREAD) if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; #endif #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; 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 valid according to the CRL. */ 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 ); /* * TODO: What happens if no CRL is present? * Suggestion: Revocation state should be unknown if no CRL is present. * For backwards compatibility this is not yet implemented. */ while( crl_list != NULL ) { if( crl_list->version == 0 || crl_list->issuer_raw.len != ca->subject_raw.len || memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, crl_list->issuer_raw.len ) != 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( md_info == NULL ) { /* * Cannot check 'unknown' hash */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); if( x509_profile_check_key( profile, crl_list->sig_pk, &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 */ /* * 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, mbedtls_x509_buf *name ) { size_t i; size_t cn_idx = 0, cn_len = strlen( cn ); if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) return( 0 ); 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 ); } /* * 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 * bottom means child is the end entity cert */ static int x509_crt_check_parent( const mbedtls_x509_crt *child, const mbedtls_x509_crt *parent, int top, int bottom ) { 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; /* Exception: self-signed end-entity certs that are locally trusted. */ if( top && bottom && child->raw.len == parent->raw.len && memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) { 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 ); } static int x509_crt_verify_top( mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, int path_cnt, int self_cnt, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { int ret; uint32_t ca_flags = 0; int check_path_cnt; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; const mbedtls_md_info_t *md_info; 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; 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; /* * Child is the top of the chain. Check against the trust_ca list. */ *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; md_info = mbedtls_md_info_from_type( child->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown', no need to try any CA */ trust_ca = NULL; } else mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) { if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) continue; check_path_cnt = path_cnt + 1; /* * Reduce check_path_cnt to check against if top of the chain is * the same as the trusted CA */ if( child->subject_raw.len == trust_ca->subject_raw.len && memcmp( child->subject_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) == 0 ) { check_path_cnt--; } /* Self signed certificates do not count towards the limit */ if( trust_ca->max_pathlen > 0 && trust_ca->max_pathlen < check_path_cnt - self_cnt ) { continue; } if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, child->sig_md, hash, mbedtls_md_get_size( md_info ), child->sig.p, child->sig.len ) != 0 ) { continue; } /* * Top of chain is signed by a trusted CA */ *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; break; } /* * If top of chain is not the same as the trusted CA send a verify request * to the callback for any issues with validity and CRL presence for the * trusted CA certificate. */ if( trust_ca != NULL && ( child->subject_raw.len != trust_ca->subject_raw.len || memcmp( child->subject_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) != 0 ) ) { #if defined(MBEDTLS_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the chain's top crt */ *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); #else ((void) ca_crl); #endif if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) ca_flags |= MBEDTLS_X509_BADCERT_EXPIRED; if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) ca_flags |= MBEDTLS_X509_BADCERT_FUTURE; if( NULL != f_vrfy ) { if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 ) { return( ret ); } } } /* Call callback on top cert */ if( NULL != f_vrfy ) { if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); } *flags |= ca_flags; return( 0 ); } static int x509_crt_verify_child( mbedtls_x509_crt *child, mbedtls_x509_crt *parent, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, int path_cnt, int self_cnt, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { int ret; uint32_t parent_flags = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; mbedtls_x509_crt *grandparent; const mbedtls_md_info_t *md_info; /* Counting intermediate self signed certificates */ if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) self_cnt++; /* path_cnt is 0 for the first intermediate CA */ if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) { *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); } 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; 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; md_info = mbedtls_md_info_from_type( child->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown' hash */ *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; } else { mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; if( 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 ) != 0 ) { *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; } } #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 ); #endif /* Look for a grandparent in trusted CAs */ for( grandparent = trust_ca; grandparent != NULL; grandparent = grandparent->next ) { if( x509_crt_check_parent( parent, grandparent, 0, path_cnt == 0 ) == 0 ) break; } if( grandparent != NULL ) { ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { /* Look for a grandparent upwards the chain */ for( grandparent = parent->next; grandparent != NULL; grandparent = grandparent->next ) { /* +2 because the current step is not yet accounted for * and because max_pathlen is one higher than it should be. * Also self signed certificates do not count to the limit. */ if( grandparent->max_pathlen > 0 && grandparent->max_pathlen < 2 + path_cnt - self_cnt ) { continue; } if( x509_crt_check_parent( parent, grandparent, 0, path_cnt == 0 ) == 0 ) break; } /* Is our parent part of the chain or at the top? */ if( grandparent != NULL ) { ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, profile, path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } } /* child is verified to be a child of the parent, call verify callback */ if( NULL != f_vrfy ) if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); *flags |= parent_flags; return( 0 ); } /* * Verify the certificate validity */ 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_with_profile( crt, trust_ca, ca_crl, &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); } /* * Verify the certificate validity, with profile */ 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 ) { size_t cn_len; int ret; int pathlen = 0, selfsigned = 0; mbedtls_x509_crt *parent; mbedtls_x509_name *name; mbedtls_x509_sequence *cur = NULL; mbedtls_pk_type_t pk_type; if( profile == NULL ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); *flags = 0; if( cn != NULL ) { name = &crt->subject; cn_len = strlen( cn ); if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) { cur = &crt->subject_alt_names; while( cur != NULL ) { if( cur->buf.len == cn_len && x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) break; if( cur->buf.len > 2 && memcmp( cur->buf.p, "*.", 2 ) == 0 && x509_check_wildcard( cn, &cur->buf ) == 0 ) { break; } cur = cur->next; } if( cur == NULL ) *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; } else { while( name != NULL ) { if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) { if( name->val.len == cn_len && x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) break; if( name->val.len > 2 && memcmp( name->val.p, "*.", 2 ) == 0 && x509_check_wildcard( cn, &name->val ) == 0 ) break; } name = name->next; } if( name == NULL ) *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; } } /* 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 ) *flags |= MBEDTLS_X509_BADCERT_BAD_PK; if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; /* Look for a parent in trusted CAs */ for( parent = trust_ca; parent != NULL; parent = parent->next ) { if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) break; } if( parent != NULL ) { ret = x509_crt_verify_top( crt, parent, ca_crl, profile, pathlen, selfsigned, flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { /* Look for a parent upwards the chain */ for( parent = crt->next; parent != NULL; parent = parent->next ) if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) break; /* Are we part of the chain or at the top? */ if( parent != NULL ) { ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, pathlen, selfsigned, flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, pathlen, selfsigned, flags, f_vrfy, p_vrfy ); if( ret != 0 ) 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; x509_crt_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; x509_crt_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; x509_crt_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; x509_crt_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); mbedtls_free( seq_prv ); } if( cert_cur->raw.p != NULL ) { x509_crt_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; x509_crt_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); if( cert_prv != crt ) mbedtls_free( cert_prv ); } while( cert_cur != NULL ); } /* Amalgamated Release Mappings */ #undef SAFE_SNPRINTF #undef BEFORE_COLON #undef BC #endif /* MBEDTLS_X509_CRT_PARSE_C */ /********* Start of file library/x509_csr.c ************/ /* * X.509 Certificate Signing Request (CSR) parsing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_X509_CSR_PARSE_C) #include #if defined(MBEDTLS_PEM_PARSE_C) #endif #if defined(MBEDTLS_PLATFORM_C) #else #include #include #define mbedtls_free free #define mbedtls_calloc calloc #define mbedtls_snprintf snprintf #endif #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) #include #endif /* Implementation that should never be optimized out by the compiler */ static void x509_csr_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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 ) 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 ); } csr->version++; if( csr->version != 1 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_UNKNOWN_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 */ 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 ); } // TODO Parse Attributes / extension requests 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 ) { int ret; #if defined(MBEDTLS_PEM_PARSE_C) size_t use_len; mbedtls_pem_context pem; #endif /* * Check for valid input */ if( csr == NULL || buf == NULL ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); #if defined(MBEDTLS_PEM_PARSE_C) 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 CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len ); if( ret == 0 ) { /* * Was PEM encoded, parse the result */ if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) return( ret ); mbedtls_pem_free( &pem ); return( 0 ); } else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) { mbedtls_pem_free( &pem ); return( ret ); } else #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 ); x509_csr_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; x509_csr_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } if( csr->raw.p != NULL ) { x509_csr_zeroize( csr->raw.p, csr->raw.len ); mbedtls_free( csr->raw.p ); } x509_csr_zeroize( csr, sizeof( mbedtls_x509_csr ) ); } /* Amalgamated Release Mappings */ #undef SAFE_SNPRINTF #undef BEFORE_COLON #undef BC #endif /* MBEDTLS_X509_CSR_PARSE_C */ /********* Start of file library/x509write_crt.c ************/ /* * X.509 certificate writing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_X509_CRT_WRITE_C) #include #if defined(MBEDTLS_PEM_WRITE_C) #endif /* MBEDTLS_PEM_WRITE_C */ /* Implementation that should never be optimized out by the compiler */ static void x509_write_crt_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } 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 ); x509_write_crt_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 ) ); mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); 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 ) ); mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); 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 */ 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; /* We currently only support 7 bits, from 0x80 to 0x02 */ if( ( key_usage & ~0xfe ) != 0 ) return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); c = buf + 4; ku = (unsigned char) key_usage; if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) return( ret ); ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), 1, buf, 4 ); 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; int ret; c = buf + 4; if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) return( ret ); ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), 0, buf, 4 ); if( ret != 0 ) return( ret ); return( 0 ); } static int x509_write_time( unsigned char **p, unsigned char *start, const char *time, size_t size ) { int ret; size_t len = 0; /* * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) */ if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) { MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, (const unsigned char *) time + 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 *) time, 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[MBEDTLS_MPI_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 */ pk_alg = mbedtls_pk_get_type( ctx->issuer_key ); if( pk_alg == MBEDTLS_PK_ECKEY ) pk_alg = MBEDTLS_PK_ECDSA; 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 */ 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) } */ 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 */ mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); 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 ) ); 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 */ /********* Start of file library/x509write_csr.c ************/ /* * X.509 Certificate Signing Request writing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * 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) #else #endif #if defined(MBEDTLS_X509_CSR_WRITE_C) #include #include #if defined(MBEDTLS_PEM_WRITE_C) #endif /* Implementation that should never be optimized out by the compiler */ static void x509_write_csr_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } 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 ); x509_write_csr_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 ); } int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) { unsigned char buf[4]; unsigned char *c; int ret; c = buf + 4; if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) return( ret ); ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), buf, 4 ); 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; int ret; c = buf + 4; if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) return( ret ); ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), buf, 4 ); 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[MBEDTLS_MPI_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 */ mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); pk_alg = mbedtls_pk_get_type( ctx->key ); if( pk_alg == MBEDTLS_PK_ECKEY ) pk_alg = MBEDTLS_PK_ECDSA; if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 || ( 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 ) ); 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 */ /********* Start of file library/xtea.c ************/ /* * An 32-bit implementation of the XTEA algorithm * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #else #endif #if defined(MBEDTLS_XTEA_C) #include #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #else #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ #if !defined(MBEDTLS_XTEA_ALT) /* Implementation that should never be optimized out by the compiler */ static void xtea_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } /* * 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; xtea_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 */ #endif /* ME_COM_MBEDTLS */