mbed TLS library
Dependents: HTTPClient-SSL WS_SERVER
Revision 0:137634ff4186, committed 2015-06-11
- Comitter:
- ansond
- Date:
- Thu Jun 11 03:27:03 2015 +0000
- Commit message:
- initial commit
Changed in this revision
diff -r 000000000000 -r 137634ff4186 README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1 @@ +June 5, 2015: mbed TLS library v1.3.11.gpl \ No newline at end of file
diff -r 000000000000 -r 137634ff4186 configs/config-ccm-psk-tls1_2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configs/config-ccm-psk-tls1_2.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,68 @@ +/* + * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites + * Distinguishing features: + * - no bignum, no PK, no X509 + * - fully modern and secure (provided the pre-shared keys have high entropy) + * - very low record overhead with CCM-8 + * - optimized for low RAM usage + * + * See README.txt for usage instructions. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +/* System support */ +#define POLARSSL_HAVE_IPV6 /* Now mandatory for NET_C */ +//#define POLARSSL_HAVE_TIME /* Optionally used in Hello messages */ +/* Other POLARSSL_HAVE_XXX flags irrelevant for this configuration */ + +/* mbed TLS feature support */ +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_DISABLE_RENEGOTIATION + +/* mbed TLS modules */ +#define POLARSSL_AES_C +#define POLARSSL_CCM_C +#define POLARSSL_CIPHER_C +#define POLARSSL_CTR_DRBG_C +#define POLARSSL_ENTROPY_C +#define POLARSSL_MD_C +#define POLARSSL_NET_C +#define POLARSSL_SHA256_C +#define POLARSSL_SSL_CLI_C +#define POLARSSL_SSL_SRV_C +#define POLARSSL_SSL_TLS_C + +/* Save RAM at the expense of ROM */ +#define POLARSSL_AES_ROM_TABLES + +/* Save some RAM by adjusting to your exact needs */ +#define POLARSSL_PSK_MAX_LEN 16 /* 128-bits keys are generally enough */ + +/* + * You should adjust this to the exact number of sources you're using: default + * is the "platform_entropy_poll" source, but you may want to add other ones + * Minimum is 2 for the entropy test suite. + */ +#define ENTROPY_MAX_SOURCES 2 + +/* + * Use only CCM_8 ciphersuites, and + * save ROM and a few bytes of RAM by specifying our own ciphersuite list + */ +#define SSL_CIPHERSUITES \ + TLS_PSK_WITH_AES_256_CCM_8, \ + TLS_PSK_WITH_AES_128_CCM_8 + +/* + * Save RAM at the expense of interoperability: do this only if you control + * both ends of the connection! (See comments in "polarssl/ssl.h".) + * The optimal size here depends on the typical size of records. + */ +#define SSL_MAX_CONTENT_LEN 512 + +#include "check_config.h" + +#endif /* POLARSSL_CONFIG_H */ +
diff -r 000000000000 -r 137634ff4186 configs/config-mini-tls1_1.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configs/config-mini-tls1_1.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,58 @@ +/* + * Minimal configuration for TLS 1.1 (RFC 4346), implementing only the + * required ciphersuite: TLS_RSA_WITH_3DES_EDE_CBC_SHA + * + * See README.txt for usage instructions. + */ + +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +/* System support */ +#define POLARSSL_HAVE_ASM +#define POLARSSL_HAVE_TIME +#define POLARSSL_HAVE_IPV6 + +/* mbed TLS feature support */ +#define POLARSSL_CIPHER_MODE_CBC +#define POLARSSL_PKCS1_V15 +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED +#define POLARSSL_SSL_PROTO_TLS1_1 +#define POLARSSL_SSL_DISABLE_RENEGOTIATION + +/* mbed TLS modules */ +#define POLARSSL_AES_C +#define POLARSSL_ASN1_PARSE_C +#define POLARSSL_ASN1_WRITE_C +#define POLARSSL_BIGNUM_C +#define POLARSSL_CIPHER_C +#define POLARSSL_CTR_DRBG_C +#define POLARSSL_DES_C +#define POLARSSL_ENTROPY_C +#define POLARSSL_MD_C +#define POLARSSL_MD5_C +#define POLARSSL_NET_C +#define POLARSSL_OID_C +#define POLARSSL_PK_C +#define POLARSSL_PK_PARSE_C +#define POLARSSL_RSA_C +#define POLARSSL_SHA1_C +#define POLARSSL_SHA256_C +#define POLARSSL_SSL_CLI_C +#define POLARSSL_SSL_SRV_C +#define POLARSSL_SSL_TLS_C +#define POLARSSL_X509_CRT_PARSE_C +#define POLARSSL_X509_USE_C + +/* For test certificates */ +#define POLARSSL_BASE64_C +#define POLARSSL_CERTS_C +#define POLARSSL_PEM_PARSE_C + +/* For testing with compat.sh */ +#define POLARSSL_FS_IO + +#include "polarssl/check_config.h" + +#endif /* POLARSSL_CONFIG_H */ +
diff -r 000000000000 -r 137634ff4186 configs/config-picocoin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configs/config-picocoin.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,54 @@ +/* + * Reduced configuration used by Picocoin. + * + * See README.txt for usage instructions. + * + * Distinguishing features: + * - no SSL/TLS; + * - no X.509; + * - ECDSA/PK and some other chosen crypto bits. + */ + +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +/* System support */ +#define POLARSSL_HAVE_LONGLONG +#define POLARSSL_HAVE_ASM +#define POLARSSL_HAVE_TIME +#define POLARSSL_HAVE_IPV6 + +/* mbed TLS feature support */ +#define POLARSSL_CIPHER_MODE_CBC +#define POLARSSL_CIPHER_PADDING_PKCS7 +#define POLARSSL_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECDSA_DETERMINISTIC +#define POLARSSL_PK_PARSE_EC_EXTENDED +#define POLARSSL_ERROR_STRERROR_DUMMY +#define POLARSSL_FS_IO + +/* mbed TLS modules */ +#define POLARSSL_AESNI_C +#define POLARSSL_AES_C +#define POLARSSL_ASN1_PARSE_C +#define POLARSSL_ASN1_WRITE_C +#define POLARSSL_BASE64_C +#define POLARSSL_BIGNUM_C +#define POLARSSL_ECDSA_C +#define POLARSSL_ECP_C +#define POLARSSL_ENTROPY_C +#define POLARSSL_HMAC_DRBG_C +#define POLARSSL_MD_C +#define POLARSSL_OID_C +#define POLARSSL_PADLOCK_C +#define POLARSSL_PK_C +#define POLARSSL_PK_PARSE_C +#define POLARSSL_PK_WRITE_C +#define POLARSSL_RIPEMD160_C +#define POLARSSL_SHA1_C +#define POLARSSL_SHA256_C + +#include "check_config.h" + +#endif /* POLARSSL_CONFIG_H */ +
diff -r 000000000000 -r 137634ff4186 configs/config-psk-rc4-tls1_0.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configs/config-psk-rc4-tls1_0.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,42 @@ +/* + * Custom compact configuration for TLS 1.0 with PSK and RC4 + * Distinguishing features: no bignum, no PK, no X509. + * + * WARNING: RC4 is in the process of being deprecated! + * This configuration is kept for testing purposes only, DO NOT USE it! + * For a safe and lean PSK-based configuration, see config-ccm-psk-tls1_2.h + * + * See README.txt for usage instructions. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +/* System support */ +#define POLARSSL_HAVE_IPV6 /* Now mandatory for NET_C */ +//#define POLARSSL_HAVE_TIME /* Optionnaly used in Hello messages */ +/* Other POLARSSL_HAVE_XXX flags irrelevant for this configuration */ + +/* mbed TLS feature support */ +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_SSL_PROTO_TLS1 +#define POLARSSL_SSL_DISABLE_RENEGOTIATION + +/* mbed TLS modules */ +#define POLARSSL_AES_C +#define POLARSSL_ARC4_C +#define POLARSSL_CIPHER_C +#define POLARSSL_CTR_DRBG_C +#define POLARSSL_ENTROPY_C +#define POLARSSL_MD_C +#define POLARSSL_MD5_C +#define POLARSSL_NET_C +#define POLARSSL_SHA1_C +#define POLARSSL_SHA256_C +#define POLARSSL_SSL_CLI_C +#define POLARSSL_SSL_SRV_C +#define POLARSSL_SSL_TLS_C + +#include "polarssl/check_config.h" + +#endif /* POLARSSL_CONFIG_H */ +
diff -r 000000000000 -r 137634ff4186 configs/config-suite-b.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configs/config-suite-b.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,97 @@ +/* + * Minimal configuration for TLS NSA Suite B Profile (RFC 6460) + * + * Distinguishing features: + * - no RSA or classic DH, fully based on ECC + * - optimized for low RAM usage + * + * Possible improvements: + * - if 128-bit security is enough, disable secp384r1 and SHA-512 + * - use embedded certs in DER format and disable PEM_PARSE_C and BASE64_C + * + * See README.txt for usage instructions. + */ + +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +/* System support */ +#define POLARSSL_HAVE_ASM +#define POLARSSL_HAVE_TIME +#define POLARSSL_HAVE_IPV6 + +/* mbed TLS feature support */ +#define POLARSSL_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define POLARSSL_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_DISABLE_RENEGOTIATION + +/* mbed TLS modules */ +#define POLARSSL_AES_C +#define POLARSSL_ASN1_PARSE_C +#define POLARSSL_ASN1_WRITE_C +#define POLARSSL_BIGNUM_C +#define POLARSSL_CIPHER_C +#define POLARSSL_CTR_DRBG_C +#define POLARSSL_ECDH_C +#define POLARSSL_ECDSA_C +#define POLARSSL_ECP_C +#define POLARSSL_ENTROPY_C +#define POLARSSL_GCM_C +#define POLARSSL_MD_C +#define POLARSSL_NET_C +#define POLARSSL_OID_C +#define POLARSSL_PK_C +#define POLARSSL_PK_PARSE_C +#define POLARSSL_SHA256_C +#define POLARSSL_SHA512_C +#define POLARSSL_SSL_CLI_C +#define POLARSSL_SSL_SRV_C +#define POLARSSL_SSL_TLS_C +#define POLARSSL_X509_CRT_PARSE_C +#define POLARSSL_X509_USE_C + +/* For test certificates */ +#define POLARSSL_BASE64_C +#define POLARSSL_CERTS_C +#define POLARSSL_PEM_PARSE_C + +/* Save RAM at the expense of ROM */ +#define POLARSSL_AES_ROM_TABLES + +/* Save RAM by adjusting to our exact needs */ +#define POLARSSL_ECP_MAX_BITS 384 +#define POLARSSL_MPI_MAX_SIZE 48 // 384 bits is 48 bytes + +/* Save RAM at the expense of speed, see ecp.h */ +#define POLARSSL_ECP_WINDOW_SIZE 2 +#define POLARSSL_ECP_FIXED_POINT_OPTIM 0 + +/* Significant speed benefit at the expense of some ROM */ +#define POLARSSL_ECP_NIST_OPTIM + +/* + * You should adjust this to the exact number of sources you're using: default + * is the "platform_entropy_poll" source, but you may want to add other ones. + * Minimum is 2 for the entropy test suite. + */ +#define ENTROPY_MAX_SOURCES 2 + +/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ +#define SSL_CIPHERSUITES \ + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* + * Save RAM at the expense of interoperability: do this only if you control + * both ends of the connection! (See coments in "polarssl/ssl.h".) + * The minimum size here depends on the certificate chain used as well as the + * typical size of records. + */ +#define SSL_MAX_CONTENT_LEN 1024 + +#include "polarssl/check_config.h" + +#endif /* POLARSSL_CONFIG_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/aes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/aes.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,279 @@ +/** + * \file aes.h + * + * \brief AES block cipher + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_AES_H +#define POLARSSL_AES_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +/* padlock.c and aesni.c rely on these values! */ +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +#if !defined(POLARSSL_AES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES context structure + * + * \note buf is able to hold 32 extra bytes, which can be used: + * - for alignment purposes if VIA padlock is used, and/or + * - to simplify key expansion in the 256-bit case by + * generating an extra round key + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t *rk; /*!< AES round keys */ + uint32_t buf[68]; /*!< unaligned data */ +} +aes_context; + +/** + * \brief Initialize AES context + * + * \param ctx AES context to be initialized + */ +void aes_init( aes_context *ctx ); + +/** + * \brief Clear AES context + * + * \param ctx AES context to be cleared + */ +void aes_free( aes_context *ctx ); + +/** + * \brief AES key schedule (encryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief AES key schedule (decryption) + * + * \param ctx AES context to be initialized + * \param key decryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief AES-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/** + * \brief AES-CFB128 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int aes_crypt_cfb128( aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief AES-CFB8 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int aes_crypt_cfb8( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/** + * \brief AES-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \param ctx AES context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int aes_crypt_ctr( 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 ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_AES_ALT */ +#include "aes_alt.h" +#endif /* POLARSSL_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int aes_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/aesni.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/aesni.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,113 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * Copyright (C) 2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_AESNI_H +#define POLARSSL_AESNI_H + +#include "aes.h" + +#define POLARSSL_AESNI_AES 0x02000000u +#define POLARSSL_AESNI_CLMUL 0x00000002u + +#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(POLARSSL_HAVE_X86_64) +#define POLARSSL_HAVE_X86_64 +#endif + +#if defined(POLARSSL_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES-NI features detection routine + * + * \param what The feature to detect + * (POLARSSL_AESNI_AES or POLARSSL_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int aesni_supports( unsigned int what ); + +/** + * \brief AES-NI AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int aesni_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief GCM multiplication: c = a * b in GF(2^128) + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Compute decryption round keys from encryption round keys + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ); + +/** + * \brief Perform key expansion (for encryption) + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_HAVE_X86_64 */ + +#endif /* POLARSSL_AESNI_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/arc4.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/arc4.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,115 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ARC4_H +#define POLARSSL_ARC4_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if !defined(POLARSSL_ARC4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 context structure + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +arc4_context; + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + */ +void arc4_init( arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + */ +void arc4_free( arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + */ +void arc4_setup( arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + */ +int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* POLARSSL_ARC4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int arc4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/asn1.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/asn1.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,346 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ASN1_H +#define POLARSSL_ASN1_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(POLARSSL_BIGNUM_C) +#include "bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define POLARSSL_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define POLARSSL_ERR_ASN1_MALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with DER encoded the ANS1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::x509_buf. + * \{ + */ +#define ASN1_BOOLEAN 0x01 +#define ASN1_INTEGER 0x02 +#define ASN1_BIT_STRING 0x03 +#define ASN1_OCTET_STRING 0x04 +#define ASN1_NULL 0x05 +#define ASN1_OID 0x06 +#define ASN1_UTF8_STRING 0x0C +#define ASN1_SEQUENCE 0x10 +#define ASN1_SET 0x11 +#define ASN1_PRINTABLE_STRING 0x13 +#define ASN1_T61_STRING 0x14 +#define ASN1_IA5_STRING 0x16 +#define ASN1_UTC_TIME 0x17 +#define ASN1_GENERALIZED_TIME 0x18 +#define ASN1_UNIVERSAL_STRING 0x1C +#define ASN1_BMP_STRING 0x1E +#define ASN1_PRIMITIVE 0x00 +#define ASN1_CONSTRUCTED 0x20 +#define ASN1_CONTEXT_SPECIFIC 0x80 +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + * + * Warning: returns true when the OIDs are equal (unlike memcmp)! + */ +#define OID_CMP(oid_str, oid_buf) \ + ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct _asn1_buf +{ + int tag; /**< ASN1 type, e.g. ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, e.g. in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct _asn1_bitstring +{ + size_t len; /**< ASN1 length, e.g. in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct _asn1_sequence +{ + asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct _asn1_sequence *next; /**< The next entry in the sequence. */ +} +asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct _asn1_named_data +{ + asn1_buf oid; /**< The object identifier. */ + asn1_buf val; /**< The named value. */ + struct _asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching + * end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is + * unparseable. + */ +int asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \return 0 if successful, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did + * not match requested tag, or another specific ASN.1 error code. + */ +int asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_bitstring( unsigned char **p, const unsigned char *end, + asn1_bitstring *bs); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>" + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + asn1_sequence *cur, + int tag); + +#if defined(POLARSSL_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mpi *X ); +#endif /* POLARSSL_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_alg( unsigned char **p, + const unsigned char *end, + asn1_buf *alg, asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +asn1_named_data *asn1_find_named_data( asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a asn1_named_data entry + * + * \param entry The named data entry to free + */ +void asn1_free_named_data( asn1_named_data *entry ); + +/** + * \brief Free all entries in a asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void asn1_free_named_data_list( asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/asn1write.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/asn1write.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,241 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ASN1_WRITE_H +#define POLARSSL_ASN1_WRITE_H + +#include "asn1.h" + +#define ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ + g += ret; } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ +int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ +int asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(POLARSSL_BIGNUM_C) +/** + * \brief Write a big number (ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ +int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ); +#endif /* POLARSSL_BIGNUM_C */ + +/** + * \brief Write a NULL tag (ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ +int asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * \param oid_len length of the OID + * + * \return the length written or a negative error code + */ +int asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * \param oid_len length of the OID + * \param par_len length of parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return the length written or a negative error code + */ +int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (ASN1_BOOLEAN) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param boolean 0 or 1 + * + * \return the length written or a negative error code + */ +int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); + +/** + * \brief Write an int tag (ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ +int asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write an IA5 string tag (ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ +int asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list Pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry) + * \param oid The OID to look for + * \param oid_len Size of the OID + * \param val Data to store (can be NULL if you want to fill it by hand) + * \param val_len Minimum length of the data buffer needed + * + * \return NULL if if there was a memory allocation error, or a pointer + * to the new / existing entry. + */ +asn1_named_data *asn1_store_named_data( asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_ASN1_WRITE_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/base64.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/base64.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,85 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BASE64_H +#define POLARSSL_BASE64_H + +#include <stddef.h> + +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. + * *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_encode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or + * POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or *dlen = 0 to obtain + * the required buffer size in *dlen + */ +int base64_decode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int base64_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/bignum.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/bignum.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,755 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BIGNUM_H +#define POLARSSL_BIGNUM_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +#if (_MSC_VER <= 1200) +typedef signed short int16_t; +typedef unsigned short uint16_t; +#else +typedef INT16 int16_t; +typedef UINT16 uint16_t; +#endif +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +#else +#include <inttypes.h> +#endif /* _MSC_VER && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define POLARSSL_MPI_MAX_LIMBS 10000 + +#if !defined(POLARSSL_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !POLARSSL_MPI_WINDOW_SIZE */ + +#if !defined(POLARSSL_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can results temporarily in larger MPIs. So the number + * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher. + */ +#define POLARSSL_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !POLARSSL_MPI_MAX_SIZE */ + +#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mpi_read_file() and writing to files with + * mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of POLARSSL_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define POLARSSL_MPI_MAX_BITS_SCALE100 ( 100 * POLARSSL_MPI_MAX_BITS ) +#define LN_2_DIV_LN_10_SCALE100 332 +#define POLARSSL_MPI_RW_BUFFER_SIZE ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise + */ +#if defined(POLARSSL_HAVE_INT8) +typedef signed char t_sint; +typedef unsigned char t_uint; +typedef uint16_t t_udbl; +#define POLARSSL_HAVE_UDBL +#else +#if defined(POLARSSL_HAVE_INT16) +typedef int16_t t_sint; +typedef uint16_t t_uint; +typedef uint32_t t_udbl; +#define POLARSSL_HAVE_UDBL +#else + /* + * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes) + * by defining POLARSSL_HAVE_INT32 and undefining POLARSSL_HAVE_ASM + */ + #if ( ! defined(POLARSSL_HAVE_INT32) && \ + defined(_MSC_VER) && defined(_M_AMD64) ) + #define POLARSSL_HAVE_INT64 + typedef int64_t t_sint; + typedef uint64_t t_uint; + #else + #if ( ! defined(POLARSSL_HAVE_INT32) && \ + defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + (defined(__sparc__) && defined(__arch64__)) || \ + defined(__s390x__) || defined(__mips64) ) ) + #define POLARSSL_HAVE_INT64 + typedef int64_t t_sint; + typedef uint64_t t_uint; + typedef unsigned int t_udbl __attribute__((mode(TI))); + #define POLARSSL_HAVE_UDBL + #else + #define POLARSSL_HAVE_INT32 + typedef int32_t t_sint; + typedef uint32_t t_uint; + #if ( defined(_MSC_VER) && defined(_M_IX86) ) + typedef uint64_t t_udbl; + #define POLARSSL_HAVE_UDBL + #else + #if defined( POLARSSL_HAVE_LONGLONG ) + typedef unsigned long long t_udbl; + #define POLARSSL_HAVE_UDBL + #endif + #endif + #endif /* !POLARSSL_HAVE_INT32 && __GNUC__ && 64-bit platform */ + #endif /* !POLARSSL_HAVE_INT32 && _MSC_VER && _M_AMD64 */ +#endif /* POLARSSL_HAVE_INT16 */ +#endif /* POLARSSL_HAVE_INT8 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + t_uint *p; /*!< pointer to limbs */ +} +mpi; + +/** + * \brief Initialize one MPI (make internal references valid) + * This just makes it ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X One MPI to initialize. + */ +void mpi_init( mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mpi_free( mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_grow( mpi *X, size_t nblimbs ); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shrink( mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_copy( mpi *X, const mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mpi_swap( mpi *X, mpi *Y ); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign ); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mpi value + * \param Y Second mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char assign ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_lset( mpi *X, t_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mpi_get_bit( const mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_lsb( const mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_msb( const mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mpi_size( const mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_string( mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param s String buffer + * \param slen String buffer size + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code. + * *slen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *slen = 0 to obtain the + * minimum required buffer size in *slen. + */ +int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Read X from an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_l( mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_r( mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mpi_cmp_abs( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mpi_cmp_mpi( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mpi_cmp_int( const mpi *X, t_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * Note: despite the functon signature, b is treated as a + * t_uint. Negative values of b are treated as large positive + * values. + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to multiply with + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Division by mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination t_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_fill_random( mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_gcd( mpi *G, const mpi *A, const mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil + POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N + */ +int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mpi_is_prime( mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/blowfish.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/blowfish.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,211 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + * + * Copyright (C) 2012-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BLOWFISH_H +#define POLARSSL_BLOWFISH_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define BLOWFISH_ENCRYPT 1 +#define BLOWFISH_DECRYPT 0 +#define BLOWFISH_MAX_KEY 448 +#define BLOWFISH_MIN_KEY 32 +#define BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +#if !defined(POLARSSL_BLOWFISH_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Blowfish context structure + */ +typedef struct +{ + uint32_t P[BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +blowfish_context; + +/** + * \brief Initialize Blowfish context + * + * \param ctx Blowfish context to be initialized + */ +void blowfish_init( blowfish_context *ctx ); + +/** + * \brief Clear Blowfish context + * + * \param ctx Blowfish context to be cleared + */ +void blowfish_free( blowfish_context *ctx ); + +/** + * \brief Blowfish key schedule + * + * \param ctx Blowfish context to be initialized + * \param key encryption key + * \param keysize must be between 32 and 448 bits + * + * \return 0 if successful, or POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH + */ +int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief Blowfish-ECB block encryption/decryption + * + * \param ctx Blowfish context + * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int blowfish_crypt_ecb( blowfish_context *ctx, + int mode, + const unsigned char input[BLOWFISH_BLOCKSIZE], + unsigned char output[BLOWFISH_BLOCKSIZE] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief Blowfish-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (8 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH + */ +int blowfish_crypt_cbc( blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/** + * \brief Blowfish CFB buffer encryption/decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int blowfish_crypt_cfb64( blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/** + * \brief Blowfish-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * \param ctx Blowfish context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 64-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int blowfish_crypt_ctr( blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[BLOWFISH_BLOCKSIZE], + unsigned char stream_block[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* POLARSSL_BLOWFISH_ALT */ + +#endif /* blowfish.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/bn_mul.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/bn_mul.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,871 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2010, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef POLARSSL_BN_MUL_H +#define POLARSSL_BN_MUL_H + +#include "bignum.h" + +#if defined(POLARSSL_HAVE_ASM) + +#if defined(__GNUC__) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(POLARSSL_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "movq %3, %%rsi \n\t" \ + "movq %4, %%rdi \n\t" \ + "movq %5, %%rcx \n\t" \ + "movq %6, %%rbx \n\t" \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + "movq %%rcx, %0 \n\t" \ + "movq %%rdi, %1 \n\t" \ + "movq %%rsi, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc64 assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) && defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); +#endif /* SPARCv9 */ + +#if defined(__sparc__) && !defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* SPARCv8 */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4" "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +#if defined(__arm__) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(POLARSSL_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* POLARSSL_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(POLARSSL_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + t_udbl r; \ + t_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (t_udbl) b; \ + r0 = (t_uint) r; \ + r1 = (t_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + t_uint s0, s1, b0, b1; \ + t_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/camellia.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/camellia.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,243 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CAMELLIA_H +#define POLARSSL_CAMELLIA_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define CAMELLIA_ENCRYPT 1 +#define CAMELLIA_DECRYPT 0 + +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +#if !defined(POLARSSL_CAMELLIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CAMELLIA context structure + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +camellia_context; + +/** + * \brief Initialize CAMELLIA context + * + * \param ctx CAMELLIA context to be initialized + */ +void camellia_init( camellia_context *ctx ); + +/** + * \brief Clear CAMELLIA context + * + * \param ctx CAMELLIA context to be cleared + */ +void camellia_free( camellia_context *ctx ); + +/** + * \brief CAMELLIA key schedule (encryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief CAMELLIA key schedule (decryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key decryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief CAMELLIA-ECB block encryption/decryption + * + * \param ctx CAMELLIA context + * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int camellia_crypt_ecb( camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief CAMELLIA-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int camellia_crypt_cbc( camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/** + * \brief CAMELLIA-CFB128 buffer encryption/decryption + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int camellia_crypt_cfb128( camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/** + * \brief CAMELLIA-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIA_DECRYPT. + * + * \param ctx CAMELLIA context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int camellia_crypt_ctr( 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 ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* POLARSSL_CAMELLIA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int camellia_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ccm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ccm.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,132 @@ +/** + * \file ccm.h + * + * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers + * + * Copyright (C) 2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CCM_H +#define POLARSSL_CCM_H + +#include "cipher.h" + +#define POLARSSL_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */ +#define POLARSSL_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CCM context structure + */ +typedef struct { + cipher_context_t cipher_ctx; /*!< cipher context used */ +} +ccm_context; + +/** + * \brief CCM initialization (encryption and decryption) + * + * \param ctx CCM context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keysize key size in bits (must be acceptable by the cipher) + * + * \return 0 if successful, or a cipher specific error code + */ +int ccm_init( ccm_context *ctx, cipher_id_t cipher, + const unsigned char *key, unsigned int keysize ); + +/** + * \brief Free a CCM context and underlying cipher sub-context + * + * \param ctx CCM context to free + */ +void ccm_free( ccm_context *ctx ); + +/** + * \brief CCM buffer encryption + * + * \param ctx CCM context + * \param length length of the input data in bytes + * \param iv nonce (initialization vector) + * \param iv_len length of IV in bytes + * must be 2, 3, 4, 5, 6, 7 or 8 + * \param add additional data + * \param add_len length of additional data in bytes + * must be less than 2^16 - 2^8 + * \param input buffer holding the input data + * \param output buffer for holding the output data + * must be at least 'length' bytes wide + * \param tag buffer for holding the tag + * \param tag_len length of the tag to generate in bytes + * must be 4, 6, 8, 10, 14 or 16 + * + * \note The tag is written to a separate buffer. To get the tag + * concatenated with the output as in the CCM spec, use + * tag = output + length and make sure the output buffer is + * at least length + tag_len wide. + * + * \return 0 if successful + */ +int ccm_encrypt_and_tag( 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 ); + +/** + * \brief CCM buffer authenticated decryption + * + * \param ctx CCM context + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * \param tag buffer holding the tag + * \param tag_len length of the tag + * + * \return 0 if successful and authenticated, + * POLARSSL_ERR_CCM_AUTH_FAILED if tag does not match + */ +int ccm_auth_decrypt( 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 ); + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ccm_self_test( int verbose ); +#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_CGM_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/certs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/certs.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,75 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + * + * Copyright (C) 2006-2010, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CERTS_H +#define POLARSSL_CERTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Concatenation of all available CA certificates */ +extern const char test_ca_list[]; + +/* + * Convenience for users who just want a certificate: + * RSA by default, or ECDSA if RSA i not available + */ +extern const char *test_ca_crt; +extern const char *test_ca_key; +extern const char *test_ca_pwd; +extern const char *test_srv_crt; +extern const char *test_srv_key; +extern const char *test_cli_crt; +extern const char *test_cli_key; + +#if defined(POLARSSL_ECDSA_C) +extern const char test_ca_crt_ec[]; +extern const char test_ca_key_ec[]; +extern const char test_ca_pwd_ec[]; +extern const char test_srv_crt_ec[]; +extern const char test_srv_key_ec[]; +extern const char test_cli_crt_ec[]; +extern const char test_cli_key_ec[]; +#endif + +#if defined(POLARSSL_RSA_C) +extern const char test_ca_crt_rsa[]; +extern const char test_ca_key_rsa[]; +extern const char test_ca_pwd_rsa[]; +extern const char test_srv_crt_rsa[]; +extern const char test_srv_key_rsa[]; +extern const char test_cli_crt_rsa[]; +extern const char test_cli_key_rsa[]; +#endif + +#if defined(POLARSSL_DHM_C) +extern const char test_dhm_params[]; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/check_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/check_config.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,496 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef POLARSSL_CHECK_CONFIG_H +#define POLARSSL_CHECK_CONFIG_H + +#if defined(POLARSSL_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "POLARSSL_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(POLARSSL_NET_C) && !defined(POLARSSL_HAVE_IPV6) +#if defined(POLARSSL_DEPRECATED_WARNING) +#warning "Using POLARSSL_NET_C without POLARSSL_HAVE_IPV6 is deprecated" +#endif +#if defined(POLARSSL_DEPRECATED_REMOVED) +#define POLARSSL_HAVE_IPV6 +#endif +#endif /* POLARSSL_NET_C && !POLARSSL_HAVE_IPV6 */ + +#if defined(POLARSSL_AESNI_C) && !defined(POLARSSL_HAVE_ASM) +#error "POLARSSL_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_CERTS_C) && !defined(POLARSSL_PEM_PARSE_C) +#error "POLARSSL_CERTS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_CTR_DRBG_C) && !defined(POLARSSL_AES_C) +#error "POLARSSL_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_DHM_C) && !defined(POLARSSL_BIGNUM_C) +#error "POLARSSL_DHM_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDH_C) && !defined(POLARSSL_ECP_C) +#error "POLARSSL_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDSA_C) && \ + ( !defined(POLARSSL_ECP_C) || \ + !defined(POLARSSL_ASN1_PARSE_C) || \ + !defined(POLARSSL_ASN1_WRITE_C) ) +#error "POLARSSL_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) && !defined(POLARSSL_HMAC_DRBG_C) +#error "POLARSSL_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECP_C) && ( !defined(POLARSSL_BIGNUM_C) || ( \ + !defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP256R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP384R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP512R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) ) ) +#error "POLARSSL_ECP_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) && \ + !defined(POLARSSL_SHA256_C)) +#error "POLARSSL_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) && \ + defined(CTR_DRBG_ENTROPY_LEN) && (CTR_DRBG_ENTROPY_LEN > 64) +#error "CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(POLARSSL_ENTROPY_C) && \ + ( !defined(POLARSSL_SHA512_C) || defined(POLARSSL_ENTROPY_FORCE_SHA256) ) \ + && defined(CTR_DRBG_ENTROPY_LEN) && (CTR_DRBG_ENTROPY_LEN > 32) +#error "CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(POLARSSL_ENTROPY_C) && \ + defined(POLARSSL_ENTROPY_FORCE_SHA256) && !defined(POLARSSL_SHA256_C) +#error "POLARSSL_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_GCM_C) && ( \ + !defined(POLARSSL_AES_C) && !defined(POLARSSL_CAMELLIA_C) ) +#error "POLARSSL_GCM_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_HAVEGE_C) && !defined(POLARSSL_TIMING_C) +#error "POLARSSL_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_HMAC_DRBG) && !defined(POLARSSL_MD_C) +#error "POLARSSL_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(POLARSSL_DHM_C) +#error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(POLARSSL_ECDH_C) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) || \ + !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) || \ + !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_MEMORY_C) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_MEMORY_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) ) +#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PADLOCK_C) && !defined(POLARSSL_HAVE_ASM) +#error "POLARSSL_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C) +#error "POLARSSL_PBKDF2_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C) +#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C) +#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PK_C) && \ + ( !defined(POLARSSL_RSA_C) && !defined(POLARSSL_ECP_C) ) +#error "POLARSSL_PK_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_EXIT_ALT) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_EXIT_MACRO) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_EXIT_MACRO) &&\ + ( defined(POLARSSL_PLATFORM_STD_EXIT) ||\ + defined(POLARSSL_PLATFORM_EXIT_ALT) ) +#error "POLARSSL_PLATFORM_EXIT_MACRO and POLARSSL_PLATFORM_STD_EXIT/POLARSSL_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_FPRINTF_MACRO) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(POLARSSL_PLATFORM_STD_FPRINTF) ||\ + defined(POLARSSL_PLATFORM_FPRINTF_ALT) ) +#error "POLARSSL_PLATFORM_FPRINTF_MACRO and POLARSSL_PLATFORM_STD_FPRINTF/POLARSSL_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(POLARSSL_PLATFORM_FREE_MACRO) &&\ + ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) ) +#error "POLARSSL_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_FREE_MACRO) &&\ + defined(POLARSSL_PLATFORM_STD_FREE) +#error "POLARSSL_PLATFORM_FREE_MACRO and POLARSSL_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(POLARSSL_PLATFORM_FREE_MACRO) && !defined(POLARSSL_PLATFORM_MALLOC_MACRO) +#error "POLARSSL_PLATFORM_MALLOC_MACRO must be defined if POLARSSL_PLATFORM_FREE_MACRO is" +#endif + +#if defined(POLARSSL_PLATFORM_MALLOC_MACRO) &&\ + ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) ) +#error "POLARSSL_PLATFORM_MALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_MALLOC_MACRO) &&\ + defined(POLARSSL_PLATFORM_STD_MALLOC) +#error "POLARSSL_PLATFORM_MALLOC_MACRO and POLARSSL_PLATFORM_STD_MALLOC cannot be defined simultaneously" +#endif + +#if defined(POLARSSL_PLATFORM_MALLOC_MACRO) && !defined(POLARSSL_PLATFORM_FREE_MACRO) +#error "POLARSSL_PLATFORM_FREE_MACRO must be defined if POLARSSL_PLATFORM_MALLOC_MACRO is" +#endif + +#if defined(POLARSSL_PLATFORM_MEMORY) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_PRINTF_ALT) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_PRINTF_MACRO) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_PRINTF_MACRO) &&\ + ( defined(POLARSSL_PLATFORM_STD_PRINTF) ||\ + defined(POLARSSL_PLATFORM_PRINTF_ALT) ) +#error "POLARSSL_PLATFORM_PRINTF_MACRO and POLARSSL_PLATFORM_STD_PRINTF/POLARSSL_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT) && ( defined(_WIN32)\ + && !defined(EFIX64) && !defined(EFI32) ) +#error "POLARSSL_PLATFORM_SNPRINTF_ALT defined but not available on Windows" +#endif + +#if defined(POLARSSL_PLATFORM_SNPRINTF_MACRO) && !defined(POLARSSL_PLATFORM_C) +#error "POLARSSL_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(POLARSSL_PLATFORM_STD_SNPRINTF) ||\ + defined(POLARSSL_PLATFORM_SNPRINTF_ALT) ) +#error "POLARSSL_PLATFORM_SNPRINTF_MACRO and POLARSSL_PLATFORM_STD_SNPRINTF/POLARSSL_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(POLARSSL_PLATFORM_STD_MEM_HDR) &&\ + !defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS) +#error "POLARSSL_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_STD_MALLOC) && !defined(POLARSSL_PLATFORM_MEMORY) +#error "POLARSSL_PLATFORM_STD_MALLOC defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_STD_MALLOC) && !defined(POLARSSL_PLATFORM_MEMORY) +#error "POLARSSL_PLATFORM_STD_MALLOC defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_STD_FREE) && !defined(POLARSSL_PLATFORM_MEMORY) +#error "POLARSSL_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_STD_EXIT) &&\ + !defined(POLARSSL_PLATFORM_EXIT_ALT) +#error "POLARSSL_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_STD_FPRINTF) &&\ + !defined(POLARSSL_PLATFORM_FPRINTF_ALT) +#error "POLARSSL_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_STD_PRINTF) &&\ + !defined(POLARSSL_PLATFORM_PRINTF_ALT) +#error "POLARSSL_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PLATFORM_STD_SNPRINTF) &&\ + !defined(POLARSSL_PLATFORM_SNPRINTF_ALT) +#error "POLARSSL_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_RSA_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) ) +#error "POLARSSL_RSA_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_PKCS1_V21) ) +#error "POLARSSL_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_SSL3) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_1) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) && ( !defined(POLARSSL_SHA1_C) && \ + !defined(POLARSSL_SHA256_C) && !defined(POLARSSL_SHA512_C) ) +#error "POLARSSL_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_CLI_C) && !defined(POLARSSL_SSL_TLS_C) +#error "POLARSSL_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) || \ + !defined(POLARSSL_MD_C) ) +#error "POLARSSL_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_SRV_C) && !defined(POLARSSL_SSL_TLS_C) +#error "POLARSSL_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \ + !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_2)) +#error "POLARSSL_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \ + defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \ + defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \ + defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \ + !defined(POLARSSL_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) && \ + !defined(POLARSSL_SSL_PROTO_TLS1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_2) +#error "POLARSSL_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(POLARSSL_SSL_PROTO_TLS1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_2) +#error "POLARSSL_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \ + ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) || \ + !defined(POLARSSL_CIPHER_MODE_CBC) ) +#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) && \ + !defined(POLARSSL_SSL_PROTO_SSL3) && !defined(POLARSSL_SSL_PROTO_TLS1) +#error "POLARSSL_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && \ + !defined(POLARSSL_X509_CRT_PARSE_C) +#error "POLARSSL_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_THREADING_PTHREAD) +#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define POLARSSL_THREADING_IMPL +#endif + +#if defined(POLARSSL_THREADING_ALT) +#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_ALT defined, but not all prerequisites" +#endif +#define POLARSSL_THREADING_IMPL +#endif + +#if defined(POLARSSL_THREADING_C) && !defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_C defined, single threading implementation required" +#endif +#undef POLARSSL_THREADING_IMPL + +#if defined(POLARSSL_VERSION_FEATURES) && !defined(POLARSSL_VERSION_C) +#error "POLARSSL_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) || \ + !defined(POLARSSL_PK_PARSE_C) ) +#error "POLARSSL_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) || \ + !defined(POLARSSL_PK_WRITE_C) ) +#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) ) +#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) ) +#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#endif /* POLARSSL_CHECK_CONFIG_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/cipher.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/cipher.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,780 @@ +/** + * \file cipher.h + * + * \brief Generic cipher wrapper. + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef POLARSSL_CIPHER_H +#define POLARSSL_CIPHER_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C) +#define POLARSSL_CIPHER_MODE_AEAD +#endif + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#define POLARSSL_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(POLARSSL_ARC4_C) +#define POLARSSL_CIPHER_MODE_STREAM +#endif + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define POLARSSL_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ + +#define POLARSSL_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + POLARSSL_CIPHER_ID_NONE = 0, + POLARSSL_CIPHER_ID_NULL, + POLARSSL_CIPHER_ID_AES, + POLARSSL_CIPHER_ID_DES, + POLARSSL_CIPHER_ID_3DES, /* Unused! */ + POLARSSL_CIPHER_ID_CAMELLIA, + POLARSSL_CIPHER_ID_BLOWFISH, + POLARSSL_CIPHER_ID_ARC4, +} cipher_id_t; + +typedef enum { + POLARSSL_CIPHER_NONE = 0, + POLARSSL_CIPHER_NULL, + POLARSSL_CIPHER_AES_128_ECB, + POLARSSL_CIPHER_AES_192_ECB, + POLARSSL_CIPHER_AES_256_ECB, + POLARSSL_CIPHER_AES_128_CBC, + POLARSSL_CIPHER_AES_192_CBC, + POLARSSL_CIPHER_AES_256_CBC, + POLARSSL_CIPHER_AES_128_CFB128, + POLARSSL_CIPHER_AES_192_CFB128, + POLARSSL_CIPHER_AES_256_CFB128, + POLARSSL_CIPHER_AES_128_CTR, + POLARSSL_CIPHER_AES_192_CTR, + POLARSSL_CIPHER_AES_256_CTR, + POLARSSL_CIPHER_AES_128_GCM, + POLARSSL_CIPHER_AES_192_GCM, + POLARSSL_CIPHER_AES_256_GCM, + POLARSSL_CIPHER_CAMELLIA_128_ECB, + POLARSSL_CIPHER_CAMELLIA_192_ECB, + POLARSSL_CIPHER_CAMELLIA_256_ECB, + POLARSSL_CIPHER_CAMELLIA_128_CBC, + POLARSSL_CIPHER_CAMELLIA_192_CBC, + POLARSSL_CIPHER_CAMELLIA_256_CBC, + POLARSSL_CIPHER_CAMELLIA_128_CFB128, + POLARSSL_CIPHER_CAMELLIA_192_CFB128, + POLARSSL_CIPHER_CAMELLIA_256_CFB128, + POLARSSL_CIPHER_CAMELLIA_128_CTR, + POLARSSL_CIPHER_CAMELLIA_192_CTR, + POLARSSL_CIPHER_CAMELLIA_256_CTR, + POLARSSL_CIPHER_CAMELLIA_128_GCM, + POLARSSL_CIPHER_CAMELLIA_192_GCM, + POLARSSL_CIPHER_CAMELLIA_256_GCM, + POLARSSL_CIPHER_DES_ECB, + POLARSSL_CIPHER_DES_CBC, + POLARSSL_CIPHER_DES_EDE_ECB, + POLARSSL_CIPHER_DES_EDE_CBC, + POLARSSL_CIPHER_DES_EDE3_ECB, + POLARSSL_CIPHER_DES_EDE3_CBC, + POLARSSL_CIPHER_BLOWFISH_ECB, + POLARSSL_CIPHER_BLOWFISH_CBC, + POLARSSL_CIPHER_BLOWFISH_CFB64, + POLARSSL_CIPHER_BLOWFISH_CTR, + POLARSSL_CIPHER_ARC4_128, + POLARSSL_CIPHER_AES_128_CCM, + POLARSSL_CIPHER_AES_192_CCM, + POLARSSL_CIPHER_AES_256_CCM, + POLARSSL_CIPHER_CAMELLIA_128_CCM, + POLARSSL_CIPHER_CAMELLIA_192_CCM, + POLARSSL_CIPHER_CAMELLIA_256_CCM, +} cipher_type_t; + +typedef enum { + POLARSSL_MODE_NONE = 0, + POLARSSL_MODE_ECB, + POLARSSL_MODE_CBC, + POLARSSL_MODE_CFB, + POLARSSL_MODE_OFB, /* Unused! */ + POLARSSL_MODE_CTR, + POLARSSL_MODE_GCM, + POLARSSL_MODE_STREAM, + POLARSSL_MODE_CCM, +} cipher_mode_t; + +typedef enum { + POLARSSL_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */ + POLARSSL_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */ + POLARSSL_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */ + POLARSSL_PADDING_ZEROS, /**< zero padding (not reversible!) */ + POLARSSL_PADDING_NONE, /**< never pad (full blocks only) */ +} cipher_padding_t; + +typedef enum { + POLARSSL_OPERATION_NONE = -1, + POLARSSL_DECRYPT = 0, + POLARSSL_ENCRYPT, +} operation_t; + +enum { + /** Undefined key length */ + POLARSSL_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys */ + POLARSSL_KEY_LENGTH_DES = 64, + /** Key length, in bits (including parity), for DES in two key EDE */ + POLARSSL_KEY_LENGTH_DES_EDE = 128, + /** Key length, in bits (including parity), for DES in three-key EDE */ + POLARSSL_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in bytes */ +#define POLARSSL_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in bytes */ +#define POLARSSL_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information. The non-mode specific functions and values. + */ +typedef struct { + + /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */ + cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(POLARSSL_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(POLARSSL_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(POLARSSL_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_length ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_length); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +} cipher_base_t; + +/** + * Cipher information. Allows cipher functions to be called in a generic way. + */ +typedef struct { + /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */ + cipher_type_t type; + + /** Cipher mode (e.g. POLARSSL_MODE_CBC) */ + cipher_mode_t mode; + + /** Cipher key length, in bits (default length for variable sized ciphers) + * (Includes parity bits for ciphers like DES) */ + unsigned int key_length; + + /** Name of the cipher */ + const char * name; + + /** IV/NONCE size, in bytes. + * For cipher that accept many sizes: recommended size */ + unsigned int iv_size; + + /** Flags for variable IV size, variable key size, etc. */ + int flags; + + /** block size, in bytes */ + unsigned int block_size; + + /** Base cipher information and functions */ + const cipher_base_t *base; + +} cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct { + /** Information about the associated cipher */ + const cipher_info_t *cipher_info; + + /** Key length to use */ + int key_length; + + /** Operation that the context's key has been initialised for */ + operation_t operation; + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for cipher mode */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for data that hasn't been encrypted yet */ + unsigned char unprocessed_data[POLARSSL_MAX_BLOCK_LENGTH]; + + /** Number of bytes that still need processing */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode */ + unsigned char iv[POLARSSL_MAX_IV_LENGTH]; + + /** IV size in bytes (for ciphers with variable-length IVs) */ + size_t iv_size; + + /** Cipher-specific context */ + void *cipher_ctx; +} cipher_context_t; + +/** + * \brief Returns the list of ciphers supported by the generic cipher module. + * + * \return a statically allocated array of ciphers, the last entry + * is 0. + */ +const int *cipher_list( void ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. + * + * \return the cipher information structure associated with the + * given cipher_name, or NULL if not found. + */ +const cipher_info_t *cipher_info_from_string( const char *cipher_name ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return the cipher information structure associated with the + * given cipher_type, or NULL if not found. + */ +const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher id, key size and mode. + * + * \param cipher_id Id of the cipher to search for + * (e.g. POLARSSL_CIPHER_ID_AES) + * \param key_length Length of the key in bits + * \param mode Cipher mode (e.g. POLARSSL_MODE_CBC) + * + * \return the cipher information structure associated with the + * given cipher_type, or NULL if not found. + */ +const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id, + int key_length, + const cipher_mode_t mode ); + +/** + * \brief Initialize a cipher_context (as NONE) + */ +void cipher_init( cipher_context_t *ctx ); + +/** + * \brief Free and clear the cipher-specific context of ctx. + * Freeing ctx itself remains the responsibility of the + * caller. + */ +void cipher_free( cipher_context_t *ctx ); + +/** + * \brief Initialises and fills the cipher context structure with + * the appropriate values. + * + * \note Currently also clears structure. In future versions you + * will be required to call cipher_init() on the structure + * first. + * + * \param ctx context to initialise. May not be NULL. + * \param cipher_info cipher to use. + * + * \return 0 on success, + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, + * POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context failed. + */ +int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info ); + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +#if defined(POLARSSL_DEPRECATED_WARNING) +#define DEPRECATED __attribute__((deprecated)) +#else +#define DEPRECATED +#endif +/** + * \brief Free the cipher-specific context of ctx. Freeing ctx + * itself remains the responsibility of the caller. + * + * \deprecated Use cipher_free() instead + * + * \param ctx Free the cipher-specific context + * + * \returns 0 + */ +int cipher_free_ctx( cipher_context_t *ctx ) DEPRECATED; +#undef DEPRECATED +#endif /* POLARSSL_DEPRECATED_REMOVED */ + +/** + * \brief Returns the block size of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return size of the cipher's blocks, or 0 if ctx has not been + * initialised. + */ +static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief Returns the mode of operation for the cipher. + * (e.g. POLARSSL_MODE_CBC) + * + * \param ctx cipher's context. Must have been initialised. + * + * \return mode of operation, or POLARSSL_MODE_NONE if ctx + * has not been initialised. + */ +static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief Returns the size of the cipher's IV/NONCE in bytes. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return If IV has not been set yet: (recommended) IV size + * (0 for ciphers not using IV/NONCE). + * If IV has already been set: actual size. + */ +static inline int cipher_get_iv_size( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return ctx->cipher_info->iv_size; +} + +/** + * \brief Returns the type of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return type of the cipher, or POLARSSL_CIPHER_NONE if ctx has + * not been initialised. + */ +static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief Returns the name of the given cipher, as a string. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return name of the cipher, or NULL if ctx was not initialised. + */ +static inline const char *cipher_get_name( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief Returns the key length of the cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return cipher's key length, in bits, or + * POLARSSL_KEY_LENGTH_NONE if ctx has not been + * initialised. + */ +static inline int cipher_get_key_size( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_KEY_LENGTH_NONE; + + return ctx->cipher_info->key_length; +} + +/** + * \brief Returns the operation of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return operation (POLARSSL_ENCRYPT or POLARSSL_DECRYPT), + * or POLARSSL_OPERATION_NONE if ctx has not been + * initialised. + */ +static inline operation_t cipher_get_operation( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief Set the key to use with the given context. + * + * \param ctx generic cipher context. May not be NULL. Must have been + * initialised using cipher_context_from_type or + * cipher_context_from_string. + * \param key The key to use. + * \param key_length key length to use, in bits. + * \param operation Operation that the key will be used for, either + * POLARSSL_ENCRYPT or POLARSSL_DECRYPT. + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails or a cipher specific + * error code. + */ +int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, + int key_length, const operation_t operation ); + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) +/** + * \brief Set padding mode, for cipher modes that use padding. + * (Default: PKCS7 padding.) + * + * \param ctx generic cipher context + * \param mode padding mode + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE + * if selected padding mode is not supported, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ); +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief Set the initialization vector (IV) or nonce + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * + * \returns 0 on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, this function has no effect. + */ +int cipher_set_iv( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ); + +/** + * \brief Finish preparation of the given context + * + * \param ctx generic cipher context + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA + * if parameter verification fails. + */ +int cipher_reset( cipher_context_t *ctx ); + +#if defined(POLARSSL_GCM_C) +/** + * \brief Add additional data (for AEAD ciphers). + * Currently only supported with GCM. + * Must be called exactly once, after cipher_reset(). + * + * \param ctx generic cipher context + * \param ad Additional data to use. + * \param ad_len Length of ad. + * + * \return 0 on success, or a specific error code. + */ +int cipher_update_ad( cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* POLARSSL_GCM_C */ + +/** + * \brief Generic cipher update function. Encrypts/decrypts + * using the given cipher context. Writes as many block + * size'd blocks of data as possible to output. Any data + * that cannot be written immediately will either be added + * to the next block, or flushed when cipher_final is + * called. + * Exception: for POLARSSL_MODE_ECB, expects single block + * in size (e.g. 16 bytes for AES) + * + * \param ctx generic cipher context + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher or a cipher specific + * error code. + * + * \note If the underlying cipher is GCM, all calls to this + * function, except the last one before cipher_finish(), + * must have ilen a multiple of the block size. + */ +int cipher_update( cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ); + +/** + * \brief Generic cipher finalisation function. If data still + * needs to be flushed from an incomplete block, data + * contained within it will be padded with the size of + * the last block, and written to the output buffer. + * + * \param ctx Generic cipher context + * \param output buffer to write data to. Needs block_size available. + * \param olen length of the data written to the output buffer. + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, + * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting or a cipher specific error code. + */ +int cipher_finish( cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(POLARSSL_GCM_C) +/** + * \brief Write tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag buffer to write the tag + * \param tag_len Length of the tag to write + * + * \return 0 on success, or a specific error code. + */ +int cipher_write_tag( cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief Check tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag Buffer holding the tag + * \param tag_len Length of the tag to check + * + * \return 0 on success, or a specific error code. + */ +int cipher_check_tag( cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* POLARSSL_GCM_C */ + +/** + * \brief Generic all-in-one encryption/decryption + * (for all ciphers except AEAD constructs). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, use iv = NULL and iv_len = 0. + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, or + * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting, or + * a cipher specific error code. + */ +int cipher_crypt( 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 ); + +#if defined(POLARSSL_CIPHER_MODE_AEAD) +/** + * \brief Generic autenticated encryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to authenticate. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer for the authentication tag + * \param tag_len desired tag length + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * a cipher specific error code. + */ +int cipher_auth_encrypt( 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 ); + +/** + * \brief Generic autenticated decryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to be authenticated. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer holding the authentication tag + * \param tag_len length of the authentication tag + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * POLARSSL_ERR_CIPHER_AUTH_FAILED if data isn't authentic, + * or a cipher specific error code. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext to + * be used by mistake, making this interface safer. + */ +int cipher_auth_decrypt( 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 ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int cipher_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_CIPHER_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/cipher_wrap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/cipher_wrap.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,56 @@ +/** + * \file cipher_wrap.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CIPHER_WRAP_H +#define POLARSSL_CIPHER_WRAP_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + cipher_type_t type; + const cipher_info_t *info; +} cipher_definition_t; + +extern const cipher_definition_t cipher_definitions[]; + +extern int supported_ciphers[]; + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_CIPHER_WRAP_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/compat-1.2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/compat-1.2.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,396 @@ +/** + * \file compat-1.2.h + * + * \brief Backwards compatibility header for PolarSSL-1.2 from PolarSSL-1.3 + * + * \deprecated Use native PolarSSL 1.3 functions instead. + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#if ! defined(POLARSSL_DEPRECATED_REMOVED) + +#if defined(POLARSSL_DEPRECATED_WARNING) +#warning "Including compat-1.2.h is deprecated" +#endif + +#ifndef POLARSSL_COMPAT_1_2_H +#define POLARSSL_COMPAT_1_2_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +// Comment out to disable prototype change warnings +#define SHOW_PROTOTYPE_CHANGE_WARNINGS + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /* _MSC_VER */ + +#if defined(_MSC_VER) +// MSVC does not support #warning +#undef SHOW_PROTOTYPE_CHANGE_WARNINGS +#endif + +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "You can disable these warnings by commenting SHOW_PROTOTYPE_CHANGE_WARNINGS in compat-1.2.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#define POLARSSL_SHA2_C +#include "sha256.h" + +/* + * SHA-2 -> SHA-256 + */ +typedef sha256_context sha2_context; + +static inline void sha2_starts( sha256_context *ctx, int is224 ) { + sha256_starts( ctx, is224 ); +} +static inline void sha2_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ) { + sha256_update( ctx, input, ilen ); +} +static inline void sha2_finish( sha256_context *ctx, unsigned char output[32] ) { + sha256_finish( ctx, output ); +} +static inline int sha2_file( const char *path, unsigned char output[32], int is224 ) { + return sha256_file( path, output, is224 ); +} +static inline void sha2( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) { + sha256( input, ilen, output, is224 ); +} +static inline void sha2_hmac_starts( sha256_context *ctx, const unsigned char *key, + size_t keylen, int is224 ) { + sha256_hmac_starts( ctx, key, keylen, is224 ); +} +static inline void sha2_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) { + sha256_hmac_update( ctx, input, ilen ); +} +static inline void sha2_hmac_finish( sha256_context *ctx, unsigned char output[32] ) { + sha256_hmac_finish( ctx, output ); +} +static inline void sha2_hmac_reset( sha256_context *ctx ) { + sha256_hmac_reset( ctx ); +} +static inline void sha2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) { + sha256_hmac( key, keylen, input, ilen, output, is224 ); +} +static inline int sha2_self_test( int verbose ) { + return sha256_self_test( verbose ); +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) +#define POLARSSL_SHA4_C +#include "sha512.h" + +/* + * SHA-4 -> SHA-512 + */ +typedef sha512_context sha4_context; + +static inline void sha4_starts( sha512_context *ctx, int is384 ) { + sha512_starts( ctx, is384 ); +} +static inline void sha4_update( sha512_context *ctx, const unsigned char *input, + size_t ilen ) { + sha512_update( ctx, input, ilen ); +} +static inline void sha4_finish( sha512_context *ctx, unsigned char output[64] ) { + sha512_finish( ctx, output ); +} +static inline int sha4_file( const char *path, unsigned char output[64], int is384 ) { + return sha512_file( path, output, is384 ); +} +static inline void sha4( const unsigned char *input, size_t ilen, + unsigned char output[32], int is384 ) { + sha512( input, ilen, output, is384 ); +} +static inline void sha4_hmac_starts( sha512_context *ctx, const unsigned char *key, + size_t keylen, int is384 ) { + sha512_hmac_starts( ctx, key, keylen, is384 ); +} +static inline void sha4_hmac_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) { + sha512_hmac_update( ctx, input, ilen ); +} +static inline void sha4_hmac_finish( sha512_context *ctx, unsigned char output[64] ) { + sha512_hmac_finish( ctx, output ); +} +static inline void sha4_hmac_reset( sha512_context *ctx ) { + sha512_hmac_reset( ctx ); +} +static inline void sha4_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ) { + sha512_hmac( key, keylen, input, ilen, output, is384 ); +} +static inline int sha4_self_test( int verbose ) { + return sha512_self_test( verbose ); +} +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_CIPHER_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "cipher_reset() prototype changed. Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_RSA_C) +#define SIG_RSA_RAW POLARSSL_MD_NONE +#define SIG_RSA_MD2 POLARSSL_MD_MD2 +#define SIG_RSA_MD4 POLARSSL_MD_MD4 +#define SIG_RSA_MD5 POLARSSL_MD_MD5 +#define SIG_RSA_SHA1 POLARSSL_MD_SHA1 +#define SIG_RSA_SHA224 POLARSSL_MD_SHA224 +#define SIG_RSA_SHA256 POLARSSL_MD_SHA256 +#define SIG_RSA_SHA384 POLARSSL_MD_SHA384 +#define SIG_RSA_SHA512 POLARSSL_MD_SHA512 +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "rsa_pkcs1_verify() prototype changed. Manual change required if used" +#warning "rsa_pkcs1_decrypt() prototype changed. Manual change required if used" +#endif +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_DHM_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "dhm_calc_secret() prototype changed. Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_GCM_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "gcm_init() prototype changed. Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_SSL_CLI_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "ssl_set_own_cert() prototype changed. Change to ssl_set_own_cert_rsa(). Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "x509.h" + +#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT POLARSSL_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_CERT_INVALID_VERSION POLARSSL_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_CERT_INVALID_ALG POLARSSL_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG POLARSSL_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_CERT_INVALID_NAME POLARSSL_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_CERT_INVALID_DATE POLARSSL_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS POLARSSL_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH POLARSSL_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE POLARSSL_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL POLARSSL_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION POLARSSL_ERR_X509_UNKNOWN_VERSION + +static inline int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ) { + return x509_serial_gets( buf, size, serial ); +} +static inline int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ) { + return x509_dn_gets( buf, size, dn ); +} +static inline int x509parse_time_expired( const x509_time *time ) { + return x509_time_expired( time ); +} +#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +#define POLARSSL_X509_PARSE_C +#include "x509_crt.h" +typedef x509_crt x509_cert; + +static inline int x509parse_crt_der( x509_cert *chain, const unsigned char *buf, + size_t buflen ) { + return x509_crt_parse_der( chain, buf, buflen ); +} +static inline int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) { + return x509_crt_parse( chain, buf, buflen ); +} +static inline int x509parse_crtfile( x509_cert *chain, const char *path ) { + return x509_crt_parse_file( chain, path ); +} +static inline int x509parse_crtpath( x509_cert *chain, const char *path ) { + return x509_crt_parse_path( chain, path ); +} +static inline int x509parse_cert_info( char *buf, size_t size, const char *prefix, + const x509_cert *crt ) { + return x509_crt_info( buf, size, prefix, crt ); +} +static inline int x509parse_verify( x509_cert *crt, x509_cert *trust_ca, + x509_crl *ca_crl, const char *cn, int *flags, + int (*f_vrfy)(void *, x509_cert *, int, int *), + void *p_vrfy ) { + return x509_crt_verify( crt, trust_ca, ca_crl, cn, flags, f_vrfy, p_vrfy ); +} +static inline int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ) { + return x509_crt_revoked( crt, crl ); +} +static inline void x509_free( x509_cert *crt ) { + x509_crt_free( crt ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_X509_CRL_PARSE_C) +#define POLARSSL_X509_PARSE_C +#include "x509_crl.h" +static inline int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) { + return x509_crl_parse( chain, buf, buflen ); +} +static inline int x509parse_crlfile( x509_crl *chain, const char *path ) { + return x509_crl_parse_file( chain, path ); +} +static inline int x509parse_crl_info( char *buf, size_t size, const char *prefix, + const x509_crl *crl ) { + return x509_crl_info( buf, size, prefix, crl ); +} +#endif /* POLARSSL_X509_CRL_PARSE_C */ + +#if defined(POLARSSL_X509_CSR_PARSE_C) +#define POLARSSL_X509_PARSE_C +#include "x509_csr.h" +static inline int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) { + return x509_csr_parse( csr, buf, buflen ); +} +static inline int x509parse_csrfile( x509_csr *csr, const char *path ) { + return x509_csr_parse_file( csr, path ); +} +static inline int x509parse_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ) { + return x509_csr_info( buf, size, prefix, csr ); +} +#endif /* POLARSSL_X509_CSR_PARSE_C */ + +#if defined(POLARSSL_SSL_TLS_C) +#include "ssl_ciphersuites.h" + +#define ssl_default_ciphersuites ssl_list_ciphersuites() +#endif + +#if defined(POLARSSL_PK_PARSE_C) && defined(POLARSSL_RSA_C) +#include "rsa.h" +#include "pk.h" + +#define POLARSSL_ERR_X509_PASSWORD_MISMATCH POLARSSL_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT POLARSSL_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG POLARSSL_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY POLARSSL_ERR_PK_INVALID_PUBKEY + +#if defined(POLARSSL_FS_IO) +static inline int x509parse_keyfile( rsa_context *rsa, const char *path, + const char *pwd ) { + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_keyfile( &pk, path, pwd ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} +static inline int x509parse_public_keyfile( rsa_context *rsa, const char *path ) { + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_public_keyfile( &pk, path ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +static inline int x509parse_key( rsa_context *rsa, const unsigned char *key, + size_t keylen, + const unsigned char *pwd, size_t pwdlen ) { + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_key( &pk, key, keylen, pwd, pwdlen ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} + +static inline int x509parse_public_key( rsa_context *rsa, + const unsigned char *key, size_t keylen ) +{ + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_public_key( &pk, key, keylen ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} +#endif /* POLARSSL_PK_PARSE_C && POLARSSL_RSA_C */ + +#if defined(POLARSSL_PK_WRITE_C) && defined(POLARSSL_RSA_C) +#include "pk.h" +static inline int x509_write_pubkey_der( unsigned char *buf, size_t len, rsa_context *rsa ) { + int ret; + pk_context ctx; + if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret ); + if( ( ret = rsa_copy( pk_rsa( ctx ), rsa ) ) != 0 ) return( ret ); + ret = pk_write_pubkey_der( &ctx, buf, len ); + pk_free( &ctx ); + return( ret ); +} +static inline int x509_write_key_der( unsigned char *buf, size_t len, rsa_context *rsa ) { + int ret; + pk_context ctx; + if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret ); + if( ( ret = rsa_copy( pk_rsa( ctx ), rsa ) ) != 0 ) return( ret ); + ret = pk_write_key_der( &ctx, buf, len ); + pk_free( &ctx ); + return( ret ); +} +#endif /* POLARSSL_PK_WRITE_C && POLARSSL_RSA_C */ +#endif /* compat-1.2.h */ +#endif /* POLARSSL_DEPRECATED_REMOVED */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/config.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,2359 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * \deprecated The compiler should be able to generate code for 32-bit + * arithmetic (required by C89). This code is likely to be at least as + * efficient as ours. + * + * Uncomment if native integers are 8-bit wide. + */ +//#define POLARSSL_HAVE_INT8 + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * \deprecated The compiler should be able to generate code for 32-bit + * arithmetic (required by C89). This code is likely to be at least as + * efficient as ours. + * + * Uncomment if native integers are 16-bit wide. + */ +//#define POLARSSL_HAVE_INT16 + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +//#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define POLARSSL_HAVE_SSE2 + +/** + * \def POLARSSL_HAVE_TIME + * + * System has time.h and time() / localtime() / gettimeofday(). + * + * Comment if your system does not support time functions + */ +//#define POLARSSL_HAVE_TIME + +/** + * \def POLARSSL_HAVE_IPV6 + * + * System supports the basic socket interface for IPv6 (RFC 3493), + * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. + * + * Note: on Windows/MingW, XP or higher is required. + * + * \warning As of 1.3.11, *not* using this flag when POLARSSL_NET_C is + * defined, is deprecated. The alternative legacy code will be removed in 2.0. + * + * Comment if your system does not support the IPv6 socket interface + */ +#define POLARSSL_HAVE_IPV6 + +/** + * \def POLARSSL_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided malloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling POLARSSL_PLATFORM_MEMORY without the + * POLARSSL_PLATFORM_{FREE,MALLOC}_MACROs will provide + * "platform_set_malloc_free()" allowing you to set an alternative malloc() and + * free() function pointer at runtime. + * + * Enabling POLARSSL_PLATFORM_MEMORY and specifying + * POLARSSL_PLATFORM_{MALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: POLARSSL_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define POLARSSL_PLATFORM_MEMORY + +/** + * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. malloc() to + * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the POLARSSL_PLATFORM_STD_XXX defines, or enabling a + * POLARSSL_PLATFORM_XXX_MACRO. + * + * Requires: POLARSSL_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def POLARSSL_PLATFORM_XXX_ALT + * + * Uncomment a macro to let mbed TLS support the function in the platform + * abstraction layer. + * + * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require POLARSSL_PLATFORM_C to be defined! + * + * WARNING: POLARSSL_PLATFORM_SNPRINTF_ALT is not available on Windows + * for compatibility reasons. + * + * WARNING: POLARSSL_PLATFORM_XXX_ALT cannot be defined at the same time as + * POLARSSL_PLATFORM_XXX_MACRO! + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define POLARSSL_PLATFORM_EXIT_ALT +//#define POLARSSL_PLATFORM_FPRINTF_ALT +//#define POLARSSL_PLATFORM_PRINTF_ALT +//#define POLARSSL_PLATFORM_SNPRINTF_ALT + +/** + * \def POLARSSL_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use POLARSSL_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define POLARSSL_DEPRECATED_WARNING + +/** + * \def POLARSSL_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define POLARSSL_DEPRECATED_REMOVED + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for hardclock(), + * get_timer(), set_alarm() and m_sleep(). + * + * Only works if you have POLARSSL_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define POLARSSL_TIMING_ALT + +/** + * \def POLARSSL_XXX_ALT + * + * Uncomment a macro to let mbed TLS use your alternate core implementation of + * a symmetric or hash algorithm (e.g. platform specific assembly optimized + * implementations). Keep in mind that the function prototypes should remain + * the same. + * + * Example: In case you uncomment POLARSSL_AES_ALT, mbed TLS will no longer + * provide the "struct aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation for core algorithm + * functions + */ +//#define POLARSSL_AES_ALT +//#define POLARSSL_ARC4_ALT +//#define POLARSSL_BLOWFISH_ALT +//#define POLARSSL_CAMELLIA_ALT +//#define POLARSSL_DES_ALT +//#define POLARSSL_XTEA_ALT +//#define POLARSSL_MD2_ALT +//#define POLARSSL_MD4_ALT +//#define POLARSSL_MD5_ALT +//#define POLARSSL_RIPEMD160_ALT +//#define POLARSSL_SHA1_ALT +//#define POLARSSL_SHA256_ALT +//#define POLARSSL_SHA512_ALT + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + */ +//#define POLARSSL_AES_ROM_TABLES + +/** + * \def POLARSSL_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define POLARSSL_CAMELLIA_SMALL_MEMORY + +/** + * \def POLARSSL_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CBC + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * TLS_ECDH_ECDSA_WITH_NULL_SHA + * TLS_ECDH_RSA_WITH_NULL_SHA + * TLS_ECDHE_ECDSA_WITH_NULL_SHA + * TLS_ECDHE_RSA_WITH_NULL_SHA + * TLS_ECDHE_PSK_WITH_NULL_SHA384 + * TLS_ECDHE_PSK_WITH_NULL_SHA256 + * TLS_ECDHE_PSK_WITH_NULL_SHA + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_PSK_WITH_NULL_SHA384 + * TLS_RSA_PSK_WITH_NULL_SHA256 + * TLS_RSA_PSK_WITH_NULL_SHA + * TLS_PSK_WITH_NULL_SHA384 + * TLS_PSK_WITH_NULL_SHA256 + * TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define POLARSSL_CIPHER_NULL_CIPHER + +/** + * \def POLARSSL_CIPHER_PADDING_XXX + * + * Uncomment or comment macros to add support for specific padding modes + * in the cipher layer with cipher modes that support padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define POLARSSL_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ +//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES + +/** + * \def POLARSSL_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with ssl_set_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +//#define POLARSSL_REMOVE_ARC4_CIPHERSUITES + +/** + * \def POLARSSL_ECP_XXXX_ENABLED + * + * Enables specific curves within the Elliptic Curve module. + * By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define POLARSSL_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED +//#define POLARSSL_ECP_DP_M221_ENABLED // Not implemented yet! +#define POLARSSL_ECP_DP_M255_ENABLED +//#define POLARSSL_ECP_DP_M383_ENABLED // Not implemented yet! +//#define POLARSSL_ECP_DP_M511_ENABLED // Not implemented yet! + +/** + * \def POLARSSL_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define POLARSSL_ECP_NIST_OPTIM + +/** + * \def POLARSSL_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: POLARSSL_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#define POLARSSL_ECDSA_DETERMINISTIC + +/** + * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + */ +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def POLARSSL_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define POLARSSL_PK_PARSE_EC_EXTENDED + +/** + * \def POLARSSL_ERROR_STRERROR_BC + * + * Make available the backward compatible error_strerror() next to the + * current polarssl_strerror(). + * + * \deprecated Do not define this and use polarssl_strerror() instead + * + * Disable if you want to really remove the error_strerror() name + */ +#define POLARSSL_ERROR_STRERROR_BC + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of polarssl_strerror() in + * third party libraries easier when POLARSSL_ERROR_C is disabled + * (no effect when POLARSSL_ERROR_C is enabled). + * + * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're + * not using polarssl_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * polarssl_strerror() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: POLARSSL_BIGNUM_C + */ +#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define POLARSSL_NO_PLATFORM_ENTROPY + +/** + * \def POLARSSL_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: POLARSSL_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both POLARSSL_SHA256_C and + * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define POLARSSL_ENTROPY_FORCE_SHA256 + +/** + * \def POLARSSL_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define POLARSSL_MEMORY_DEBUG + +/** + * \def POLARSSL_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define POLARSSL_MEMORY_BACKTRACE + +/** + * \def POLARSSL_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: POLARSSL_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define POLARSSL_PKCS1_V15 + +/** + * \def POLARSSL_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define POLARSSL_RSA_NO_CRT + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define POLARSSL_SELF_TEST + +/** + * \def POLARSSL_SSL_AEAD_RANDOM_IV + * + * Generate a random IV rather than using the record sequence number as a + * nonce for ciphersuites using and AEAD algorithm (GCM or CCM). + * + * Using the sequence number is generally recommended. + * + * Uncomment this macro to always use random IVs with AEAD ciphersuites. + */ +//#define POLARSSL_SSL_AEAD_RANDOM_IV + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define POLARSSL_SSL_DEBUG_ALL + +/** \def POLARSSL_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: POLARSSL_SSL_PROTO_TLS1 or + * POLARSSL_SSL_PROTO_TLS1_1 or + * POLARSSL_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define POLARSSL_SSL_ENCRYPT_THEN_MAC + +/** \def POLARSSL_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: POLARSSL_SSL_PROTO_TLS1 or + * POLARSSL_SSL_PROTO_TLS1_1 or + * POLARSSL_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET + +/** + * \def POLARSSL_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +#define POLARSSL_SSL_FALLBACK_SCSV + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define POLARSSL_SSL_HW_RECORD_ACCEL + +/** + * \def POLARSSL_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +#define POLARSSL_SSL_CBC_RECORD_SPLITTING + +/** + * \def POLARSSL_SSL_DISABLE_RENEGOTIATION + * + * Disable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Warning: in the next stable branch, this switch will be replaced by + * POLARSSL_SSL_RENEGOTIATION to enable support for renegotiation. + * + * Uncomment this to disable support for renegotiation. + */ +//#define POLARSSL_SSL_DISABLE_RENEGOTIATION + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C). + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (POLARSSL_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def POLARSSL_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +#define POLARSSL_SSL_PROTO_SSL3 + +/** + * \def POLARSSL_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define POLARSSL_SSL_PROTO_TLS1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 + */ +#define POLARSSL_SSL_PROTO_TLS1_1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2. + * + * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 + */ +#define POLARSSL_SSL_PROTO_TLS1_2 + +/** + * \def POLARSSL_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#define POLARSSL_SSL_ALPN + +/** + * \def POLARSSL_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * + * Requires: POLARSSL_AES_C + * POLARSSL_SHA256_C + * POLARSSL_CIPHER_MODE_CBC + * + * Comment this macro to disable support for SSL session tickets + */ +#define POLARSSL_SSL_SESSION_TICKETS + +/** + * \def POLARSSL_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: POLARSSL_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define POLARSSL_SSL_SERVER_NAME_INDICATION + +/** + * \def POLARSSL_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define POLARSSL_SSL_TRUNCATED_HMAC + +/** + * \def POLARSSL_SSL_SET_CURVES + * + * Enable ssl_set_curves(). + * + * This is disabled by default since it breaks binary compatibility with the + * 1.3.x line. If you choose to enable it, you will need to rebuild your + * application against the new header files, relinking will not be enough. + * It will be enabled by default, or no longer an option, in the 1.4 branch. + * + * Uncomment to make ssl_set_curves() available. + */ +//#define POLARSSL_SSL_SET_CURVES + +/** + * \def POLARSSL_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define POLARSSL_THREADING_ALT + +/** + * \def POLARSSL_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define POLARSSL_THREADING_PTHREAD + +/** + * \def POLARSSL_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via version_check_feature(). + * + * Requires: POLARSSL_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define POLARSSL_VERSION_FEATURES + +/** + * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def POLARSSL_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define POLARSSL_X509_CHECK_KEY_USAGE + +/** + * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def POLARSSL_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define POLARSSL_X509_RSASSA_PSS_SUPPORT + +/** + * \def POLARSSL_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define POLARSSL_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def POLARSSL_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define POLARSSL_AESNI_C + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_PSK_WITH_RC4_128_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define POLARSSL_CAMELLIA_C + +/** + * \def POLARSSL_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define POLARSSL_CCM_C + +/** + * \def POLARSSL_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * Requires: POLARSSL_PEM_PARSE_C + * + * This module is used for testing (ssl_client/server). + */ +#define POLARSSL_CERTS_C + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define POLARSSL_CTR_DRBG_C + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: POLARSSL_ECP_C + */ +#define POLARSSL_ECDH_C + +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C + */ +#define POLARSSL_ECDSA_C + +/** + * \def POLARSSL_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * + * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED + */ +#define POLARSSL_ECP_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C + * + * This module provides a generic entropy pool + */ +#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables polarssl_strerror(). + */ +#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define POLARSSL_HAVEGE_C + +/** + * \def POLARSSL_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: POLARSSL_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define POLARSSL_HMAC_DRBG_C + +/** + * \def POLARSSL_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define POLARSSL_MD2_C + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define POLARSSL_MD4_C + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_MEMORY_C + * + * \deprecated Use POLARSSL_PLATFORM_MEMORY instead. + * + * Depends on: POLARSSL_PLATFORM_C + */ +//#define POLARSSL_MEMORY_C + +/** + * \def POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: POLARSSL_PLATFORM_C + * POLARSSL_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define POLARSSL_MEMORY_BUFFER_ALLOC_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * \warning As of 1.3.11, it is deprecated to enable this module without + * POLARSSL_HAVE_IPV6. The alternative legacy code will be removed in 2.0. + * + * Module: library/net.c + * + * This module provides TCP/IP networking routines. + */ +//#define POLARSSL_NET_C + +/** + * \def POLARSSL_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define POLARSSL_OID_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define POLARSSL_PADLOCK_C + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function. + * + * \deprecated Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. + */ +#define POLARSSL_PBKDF2_C + +/** + * \def POLARSSL_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define POLARSSL_PEM_PARSE_C + +/** + * \def POLARSSL_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define POLARSSL_PEM_WRITE_C + +/** + * \def POLARSSL_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define POLARSSL_PK_C + +/** + * \def POLARSSL_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define POLARSSL_PK_PARSE_C + +/** + * \def POLARSSL_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define POLARSSL_PK_WRITE_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: POLARSSL_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define POLARSSL_PKCS11_C + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C + * Can use: POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define POLARSSL_PKCS12_C + +/** + * \def POLARSSL_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like malloc(), free(), snprintf(), printf(), fprintf(), exit() + * + * Enabling POLARSSL_PLATFORM_C enables to use of POLARSSL_PLATFORM_XXX_ALT + * or POLARSSL_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define POLARSSL_PLATFORM_C + +/** + * \def POLARSSL_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +#define POLARSSL_RIPEMD160_C + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA2_C) + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA256_C + +/** + * \def POLARSSL_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA4_C) + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA512_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C + * and at least one of the POLARSSL_SSL_PROTO_* defines + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either POLARSSL_THREADING_ALT or + * POLARSSL_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define POLARSSL_THREADING_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, + * POLARSSL_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define POLARSSL_X509_USE_C + +/** + * \def POLARSSL_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_CRT_PARSE_C + +/** + * \def POLARSSL_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define POLARSSL_X509_CRL_PARSE_C + +/** + * \def POLARSSL_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define POLARSSL_X509_CSR_PARSE_C + +/** + * \def POLARSSL_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define POLARSSL_X509_CREATE_C + +/** + * \def POLARSSL_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define POLARSSL_X509_CRT_WRITE_C + +/** + * \def POLARSSL_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define POLARSSL_X509_CSR_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define POLARSSL_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define POLARSSL_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +/* Memory buffer allocator options */ +//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define POLARSSL_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ + +/* To Use Function Macros POLARSSL_PLATFORM_C must be enabled */ +/* POLARSSL_PLATFORM_XXX_MACRO and POLARSSL_PLATFORM_XXX_ALT cannot both be defined */ +//#define POLARSSL_PLATFORM_MALLOC_MACRO malloc /**< Default allocator macro to use, can be undefined */ +//#define POLARSSL_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define POLARSSL_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define POLARSSL_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define POLARSSL_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +//#define POLARSSL_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ + +/* SSL Cache options */ +//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ +//#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +//#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define POLARSSL_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* Debug options */ +//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ + +/* X509 options */ +//#define POLARSSL_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ + +/* \} name SECTION: Module configuration options */ + +#include "check_config.h" + +#endif /* POLARSSL_CONFIG_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ctr_drbg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ctr_drbg.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,274 @@ +/** + * \file ctr_drbg.h + * + * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CTR_DRBG_H +#define POLARSSL_CTR_DRBG_H + +#include "aes.h" + +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ + +#define CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ +#define CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ +#define CTR_DRBG_KEYBITS ( CTR_DRBG_KEYSIZE * 8 ) +#define CTR_DRBG_SEEDLEN ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE ) + /**< The seed length (counter + AES key) */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(CTR_DRBG_ENTROPY_LEN) +#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256) +#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#else +#define CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#endif +#endif + +#if !defined(CTR_DRBG_RESEED_INTERVAL) +#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(CTR_DRBG_MAX_INPUT) +#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(CTR_DRBG_MAX_REQUEST) +#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(CTR_DRBG_MAX_SEED_INPUT) +#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CTR_DRBG context structure + */ +typedef struct +{ + unsigned char counter[16]; /*!< counter (V) */ + int reseed_counter; /*!< reseed counter */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + size_t entropy_len; /*!< amount of entropy grabbed on each + (re)seed */ + int reseed_interval; /*!< reseed interval */ + + aes_context aes_ctx; /*!< AES context */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + + void *p_entropy; /*!< context for the entropy function */ +} +ctr_drbg_context; + +/** + * \brief CTR_DRBG initialization + * + * Note: Personalization data can be provided in addition to the more generic + * entropy source to make this instantiation as unique as possible. + * + * \param ctx CTR_DRBG context to be initialized + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int ctr_drbg_init( ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Clear CTR_CRBG context data + * + * \param ctx CTR_DRBG context to clear + */ +void ctr_drbg_free( ctr_drbg_context *ctx ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx CTR_DRBG context + * \param resistance CTR_DRBG_PR_ON or CTR_DRBG_PR_OFF + */ +void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each (re)seed + * (Default: CTR_DRBG_ENTROPY_LEN) + * + * \param ctx CTR_DRBG context + * \param len Amount of entropy to grab + */ +void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: CTR_DRBG_RESEED_INTERVAL) + * + * \param ctx CTR_DRBG context + * \param interval Reseed interval + */ +void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, + int interval ); + +/** + * \brief CTR_DRBG reseeding (extracts data from entropy source) + * + * \param ctx CTR_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int ctr_drbg_reseed( ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief CTR_DRBG update state + * + * \param ctx CTR_DRBG context + * \param additional Additional data to update state with + * \param add_len Length of additional data + * + * \note If add_len is greater than CTR_DRBG_MAX_SEED_INPUT, + * only the first CTR_DRBG_MAX_SEED_INPUT bytes are used, + * the remaining ones are silently discarded. + */ +void ctr_drbg_update( ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief CTR_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (Can be NULL) + * \param add_len Length of additional data + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG + */ +int ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief CTR_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG + */ +int ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error, + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG + */ +int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ctr_drbg_self_test( int verbose ); + +/* Internal functions (do not call directly) */ +int ctr_drbg_init_entropy_len( ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t ); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/debug.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,152 @@ +/** + * \file debug.h + * + * \brief Debug functions + * + * Copyright (C) 2006-2011, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_DEBUG_H +#define POLARSSL_DEBUG_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(POLARSSL_ECP_C) +#include "ecp.h" +#endif + +#if defined(POLARSSL_DEBUG_C) + +#define POLARSSL_DEBUG_LOG_FULL 0 /**< Include file:line in log lines */ +#define POLARSSL_DEBUG_LOG_RAW 1 /**< Only log raw debug lines */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_DEBUG_DFL_MODE) +#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ +#endif + +/* \} name SECTION: Module settings */ + + +#define SSL_DEBUG_MSG( level, args ) \ + debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args ); + +#define SSL_DEBUG_RET( level, text, ret ) \ + debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ); + +#define SSL_DEBUG_BUF( level, text, buf, len ) \ + debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ); + +#if defined(POLARSSL_BIGNUM_C) +#define SSL_DEBUG_MPI( level, text, X ) \ + debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ); +#endif + +#if defined(POLARSSL_ECP_C) +#define SSL_DEBUG_ECP( level, text, X ) \ + debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +#define SSL_DEBUG_CRT( level, text, crt ) \ + debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ); +#endif + +#else /* POLARSSL_DEBUG_C */ + +#define SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) + +#endif /* POLARSSL_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the log mode for the debug functions globally + * (Default value: POLARSSL_DEBUG_DFL_MODE) + * + * \param log_mode The log mode to use (POLARSSL_DEBUG_LOG_FULL or + * POLARSSL_DEBUG_LOG_RAW) + */ +void debug_set_log_mode( int log_mode ); + +/** + * \brief Set the level threshold to handle globally. Messages that have a + * level over the threshold value are ignored. + * (Default value: 0 (No debug)) + * + * \param threshold maximum level of messages to pass on + */ +void debug_set_threshold( int threshold ); + +char *debug_fmt( const char *format, ... ); + +void debug_print_msg( const ssl_context *ssl, int level, + const char *file, int line, const char *text ); + +void debug_print_ret( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +void debug_print_buf( const ssl_context *ssl, int level, + const char *file, int line, const char *text, + unsigned char *buf, size_t len ); + +#if defined(POLARSSL_BIGNUM_C) +void debug_print_mpi( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mpi *X ); +#endif + +#if defined(POLARSSL_ECP_C) +void debug_print_ecp( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const ecp_point *X ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +void debug_print_crt( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const x509_crt *crt ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/des.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/des.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,306 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_DES_H +#define POLARSSL_DES_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +#define DES_KEY_SIZE 8 + +#if !defined(POLARSSL_DES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + uint32_t sk[32]; /*!< DES subkeys */ +} +des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +des3_context; + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + */ +void des_init( des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + */ +void des_free( des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void des3_init( des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void des3_free( des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + */ +void des_key_set_parity( unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + */ +int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + */ +int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int des3_set2key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int des3_set2key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int des3_set3key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int des3_set3key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode DES_ENCRYPT or DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + */ +int des_crypt_cbc( des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int des3_crypt_ecb( des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode DES_ENCRYPT or DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH + */ +int des3_crypt_cbc( des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_DES_ALT */ +#include "des_alt.h" +#endif /* POLARSSL_DES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int des_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/dhm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/dhm.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,309 @@ +/** + * \file dhm.h + * + * \brief Diffie-Hellman-Merkle key exchange + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_DHM_H +#define POLARSSL_DHM_H + +#include "bignum.h" + +/* + * DHM Error codes + */ +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define POLARSSL_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define POLARSSL_ERR_DHM_MALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define POLARSSL_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read/write of file failed. */ + +/** + * RFC 2409 defines a number of standardized Diffie-Hellman groups + * that can be used. + * RFC 3526 defines a number of standardized Diffie-Hellman groups + * for IKE. + * RFC 5114 defines a number of standardized Diffie-Hellman groups + * that can be used. + * + * Some are included here for convenience. + * + * Included are: + * RFC 2409 6.2. 1024-bit MODP Group (Second Oakley Group) + * RFC 3526 3. 2048-bit MODP Group + * RFC 3526 4. 3072-bit MODP Group + * RFC 5114 2.1. 1024-bit MODP Group with 160-bit Prime Order Subgroup + * RFC 5114 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup + */ +#define POLARSSL_DHM_RFC2409_MODP_1024_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ + "FFFFFFFFFFFFFFFF" + +#define POLARSSL_DHM_RFC2409_MODP_1024_G "02" + +#define POLARSSL_DHM_RFC3526_MODP_2048_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" + +#define POLARSSL_DHM_RFC3526_MODP_2048_G "02" + +#define POLARSSL_DHM_RFC3526_MODP_3072_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" + +#define POLARSSL_DHM_RFC3526_MODP_3072_G "02" + +#define POLARSSL_DHM_RFC5114_MODP_1024_P \ + "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6" \ + "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" \ + "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70" \ + "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" \ + "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708" \ + "DF1FB2BC2E4A4371" + +#define POLARSSL_DHM_RFC5114_MODP_1024_G \ + "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F" \ + "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" \ + "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1" \ + "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" \ + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24" \ + "855E6EEB22B3B2E5" + +#define POLARSSL_DHM_RFC5114_MODP_2048_P \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" + +#define POLARSSL_DHM_RFC5114_MODP_2048_G \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"\ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"\ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"\ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"\ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"\ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF"\ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"\ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"\ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"\ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"\ + "81BC087F2A7065B384B890D3191F2BFA" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DHM context structure + */ +typedef struct +{ + size_t len; /*!< size(P) in chars */ + mpi P; /*!< prime modulus */ + mpi G; /*!< generator */ + mpi X; /*!< secret value */ + mpi GX; /*!< self = G^X mod P */ + mpi GY; /*!< peer = G^Y mod P */ + mpi K; /*!< key = GY^X mod P */ + mpi RP; /*!< cached R^2 mod P */ + mpi Vi; /*!< blinding value */ + mpi Vf; /*!< un-blinding value */ + mpi pX; /*!< previous X */ +} +dhm_context; + +/** + * \brief Initialize DHM context + * + * \param ctx DHM context to be initialized + */ +void dhm_init( dhm_context *ctx ); + +/** + * \brief Parse the ServerKeyExchange parameters + * + * \param ctx DHM context + * \param p &(start of input buffer) + * \param end end of buffer + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_read_params( dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief Setup and write the ServerKeyExchange parameters + * + * \param ctx DHM context + * \param x_size private value size in bytes + * \param output destination buffer + * \param olen number of chars written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note This function assumes that ctx->P and ctx->G + * have already been properly set (for example + * using mpi_read_string or mpi_read_binary). + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_make_params( dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Import the peer's public value G^Y + * + * \param ctx DHM context + * \param input input buffer + * \param ilen size of buffer + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_read_public( dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief Create own private value X and export G^X + * + * \param ctx DHM context + * \param x_size private value size in bytes + * \param output destination buffer + * \param olen must be equal to ctx->P.len + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_make_public( dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Derive and export the shared secret (G^Y)^X mod P + * + * \param ctx DHM context + * \param output destination buffer + * \param olen on entry, must hold the size of the destination buffer + * on exit, holds the actual number of bytes written + * \param f_rng RNG function, for blinding purposes + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + * + * \note If non-NULL, f_rng is used to blind the input as + * countermeasure against timing attacks. Blinding is + * automatically used if and only if our secret value X is + * re-used and costs nothing otherwise, so it is recommended + * to always pass a non-NULL f_rng argument. + */ +int dhm_calc_secret( dhm_context *ctx, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Free and clear the components of a DHM key + * + * \param ctx DHM context to free and clear + */ +void dhm_free( dhm_context *ctx ); + +#if defined(POLARSSL_ASN1_PARSE_C) +/** \ingroup x509_module */ +/** + * \brief Parse DHM parameters + * + * \param dhm DHM context to be initialized + * \param dhmin input buffer + * \param dhminlen size of the buffer + * + * \return 0 if successful, or a specific DHM or PEM error code + */ +int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(POLARSSL_FS_IO) +/** \ingroup x509_module */ +/** + * \brief Load and parse DHM parameters + * + * \param dhm DHM context to be initialized + * \param path filename to read the DHM Parameters from + * + * \return 0 if successful, or a specific DHM or PEM error code + */ +int dhm_parse_dhmfile( dhm_context *dhm, const char *path ); +#endif /* POLARSSL_FS_IO */ +#endif /* POLARSSL_ASN1_PARSE_C */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int dhm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* dhm.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ecdh.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ecdh.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,223 @@ +/** + * \file ecdh.h + * + * \brief Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ECDH_H +#define POLARSSL_ECDH_H + +#include "ecp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * When importing from an EC key, select if it is our key or the peer's key + */ +typedef enum +{ + POLARSSL_ECDH_OURS, + POLARSSL_ECDH_THEIRS, +} ecdh_side; + +/** + * \brief ECDH context structure + */ +typedef struct +{ + ecp_group grp; /*!< elliptic curve used */ + mpi d; /*!< our secret value (private key) */ + ecp_point Q; /*!< our public value (public key) */ + ecp_point Qp; /*!< peer's public value (public key) */ + mpi z; /*!< shared secret */ + int point_format; /*!< format for point export in TLS messages */ + ecp_point Vi; /*!< blinding value (for later) */ + ecp_point Vf; /*!< un-blinding value (for later) */ + mpi _d; /*!< previous d (for later) */ +} +ecdh_context; + +/** + * \brief Generate a public key. + * Raw function that only does the core computation. + * + * \param grp ECP group + * \param d Destination MPI (secret exponent, aka private key) + * \param Q Destination point (public key) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute shared secret + * Raw function that only does the core computation. + * + * \param grp ECP group + * \param z Destination MPI (shared secret) + * \param Q Public key from other party + * \param d Our secret exponent (private key) + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + * + * \note If f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks, see \c ecp_mul() for details. + */ +int ecdh_compute_shared( ecp_group *grp, mpi *z, + const ecp_point *Q, const mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Initialize context + * + * \param ctx Context to initialize + */ +void ecdh_init( ecdh_context *ctx ); + +/** + * \brief Free context + * + * \param ctx Context to free + */ +void ecdh_free( ecdh_context *ctx ); + +/** + * \brief Generate a public key and a TLS ServerKeyExchange payload. + * (First function used by a TLS server for ECDHE.) + * + * \param ctx ECDH context + * \param olen number of chars written + * \param buf destination buffer + * \param blen length of buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note This function assumes that ctx->grp has already been + * properly set (for example using ecp_use_known_dp). + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_make_params( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Parse and procress a TLS ServerKeyExhange payload. + * (First function used by a TLS client for ECDHE.) + * + * \param ctx ECDH context + * \param buf pointer to start of input buffer + * \param end one past end of buffer + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_read_params( ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ); + +/** + * \brief Setup an ECDH context from an EC key. + * (Used by clients and servers in place of the + * ServerKeyEchange for static ECDH: import ECDH parameters + * from a certificate's EC key information.) + * + * \param ctx ECDH constext to set + * \param key EC key to use + * \param side Is it our key (1) or the peer's key (0) ? + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key, + ecdh_side side ); + +/** + * \brief Generate a public key and a TLS ClientKeyExchange payload. + * (Second function used by a TLS client for ECDH(E).) + * + * \param ctx ECDH context + * \param olen number of bytes actually written + * \param buf destination buffer + * \param blen size of destination buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_make_public( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Parse and process a TLS ClientKeyExchange payload. + * (Second function used by a TLS server for ECDH(E).) + * + * \param ctx ECDH context + * \param buf start of input buffer + * \param blen length of input buffer + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_read_public( ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief Derive and export the shared secret. + * (Last function used by both TLS client en servers.) + * + * \param ctx ECDH context + * \param olen number of bytes written + * \param buf destination buffer + * \param blen buffer length + * \param f_rng RNG function, see notes for \c ecdh_compute_shared() + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ecdh_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ecdsa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ecdsa.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,231 @@ +/** + * \file ecdsa.h + * + * \brief Elliptic curve DSA + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ECDSA_H +#define POLARSSL_ECDSA_H + +#include "ecp.h" +#include "md.h" + +/** + * \brief ECDSA context structure + * + * \note Purposefully begins with the same members as struct ecp_keypair. + */ +typedef struct +{ + ecp_group grp; /*!< elliptic curve used */ + mpi d; /*!< secret signature key */ + ecp_point Q; /*!< public signature key */ + mpi r; /*!< first integer from signature */ + mpi s; /*!< second integer from signature */ +} +ecdsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Compute ECDSA signature of a previously hashed message + * + * \param grp ECP group + * \param r First output integer + * \param s Second output integer + * \param d Private signing key + * \param buf Message hash + * \param blen Length of buf + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s, + const mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/** + * \brief Compute ECDSA signature of a previously hashed message + * (deterministic version) + * + * \param grp ECP group + * \param r First output integer + * \param s Second output integer + * \param d Private signing key + * \param buf Message hash + * \param blen Length of buf + * \param md_alg MD algorithm used to hash the message + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s, + const mpi *d, const unsigned char *buf, size_t blen, + md_type_t md_alg ); +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/** + * \brief Verify ECDSA signature of a previously hashed message + * + * \param grp ECP group + * \param buf Message hash + * \param blen Length of buf + * \param Q Public key to use for verification + * \param r First integer of the signature + * \param s Second integer of the signature + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdsa_verify( ecp_group *grp, + const unsigned char *buf, size_t blen, + const ecp_point *Q, const mpi *r, const mpi *s); + +/** + * \brief Compute ECDSA signature and write it to buffer, + * serialized as defined in RFC 4492 page 20. + * (Not thread-safe to use same context in multiple threads) + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note The "sig" buffer must be at least as large as twice the + * size of the curve used, plus 7 (eg. 71 bytes if a 256-bit + * curve is used). + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or + * POLARSSL_ERR_ASN1 error code + */ +int ecdsa_write_signature( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/** + * \brief Compute ECDSA signature and write it to buffer, + * serialized as defined in RFC 4492 page 20. + * Deterministic version, RFC 6979. + * (Not thread-safe to use same context in multiple threads) + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param md_alg MD algorithm used to hash the message + * + * \note The "sig" buffer must be at least as large as twice the + * size of the curve used, plus 7 (eg. 71 bytes if a 256-bit + * curve is used). + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or + * POLARSSL_ERR_ASN1 error code + */ +int ecdsa_write_signature_det( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + md_type_t md_alg ); +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/** + * \brief Read and verify an ECDSA signature + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Size of hash + * \param sig Signature to read and verify + * \param slen Size of sig + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * POLARSSL_ERR_ECP_SIG_LEN_MISTMATCH if the signature is + * valid but its actual length is less than siglen, + * or a POLARSSL_ERR_ECP or POLARSSL_ERR_MPI error code + */ +int ecdsa_read_signature( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief Generate an ECDSA keypair on the given curve + * + * \param ctx ECDSA context in which the keypair should be stored + * \param gid Group (elliptic curve) to use. One of the various + * POLARSSL_ECP_DP_XXX macros depending on configuration. + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a POLARSSL_ERR_ECP code. + */ +int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Set an ECDSA context from an EC key pair + * + * \param ctx ECDSA context to set + * \param key EC key to use + * + * \return 0 on success, or a POLARSSL_ERR_ECP code. + */ +int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key ); + +/** + * \brief Initialize context + * + * \param ctx Context to initialize + */ +void ecdsa_init( ecdsa_context *ctx ); + +/** + * \brief Free context + * + * \param ctx Context to free + */ +void ecdsa_free( ecdsa_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ecdsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ecp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ecp.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,665 @@ +/** + * \file ecp.h + * + * \brief Elliptic curves over GF(p) + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ECP_H +#define POLARSSL_ECP_H + +#include "bignum.h" + +/* + * ECP error codes + */ +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define POLARSSL_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define POLARSSL_ERR_ECP_MALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define POLARSSL_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define POLARSSL_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain parameters (curve, subgroup and generator) identifiers. + * + * Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only well-known domain parameters from trusted + * sources should be used. See ecp_use_known_dp(). + */ +typedef enum +{ + POLARSSL_ECP_DP_NONE = 0, + POLARSSL_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ + POLARSSL_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ + POLARSSL_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ + POLARSSL_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ + POLARSSL_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ + POLARSSL_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ + POLARSSL_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ + POLARSSL_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ + POLARSSL_ECP_DP_M221, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_M255, /*!< Curve25519 */ + POLARSSL_ECP_DP_M383, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_M511, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ + POLARSSL_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ + POLARSSL_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ +} ecp_group_id; + +/** + * Number of supported curves (plus one for NONE). + * + * (Montgomery curves excluded for now.) + */ +#define POLARSSL_ECP_DP_MAX 12 + +/** + * Curve information for use by other modules + */ +typedef struct +{ + ecp_group_id grp_id; /*!< Internal identifier */ + uint16_t tls_id; /*!< TLS NamedCurve identifier */ + uint16_t size; /*!< Curve size in bits */ + const char *name; /*!< Human-friendly name */ +} ecp_curve_info; + +/** + * \brief ECP point structure (jacobian coordinates) + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or Z == 1. (Other + * values of Z are used by internal functions only.) + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, X and Y are its standard (affine) coordinates. + */ +typedef struct +{ + mpi X; /*!< the point's X coordinate */ + mpi Y; /*!< the point's Y coordinate */ + mpi Z; /*!< the point's Z coordinate */ +} +ecp_point; + +/** + * \brief ECP group structure + * + * We consider two types of curves equations: + * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) + * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (M255 + draft) + * In both cases, a generator G for a prime-order subgroup is fixed. In the + * short weierstrass, this subgroup is actually the whole curve, and its + * cardinal is denoted by N. + * + * In the case of Short Weierstrass curves, our code requires that N is an odd + * prime. (Use odd in ecp_mul() and prime in ecdsa_sign() for blinding.) + * + * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is + * the quantity actually used in the formulas. Also, nbits is not the size of N + * but the required size for private keys. + * + * If modp is NULL, reduction modulo P is done using a generic algorithm. + * Otherwise, it must point to a function that takes an mpi in the range + * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more + * than pbits, so that the integer may be efficiently brought in the 0..P-1 + * range by a few additions or substractions. It must return 0 on success and + * non-zero on failure. + */ +typedef struct +{ + ecp_group_id id; /*!< internal group identifier */ + mpi P; /*!< prime modulus of the base field */ + mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ + mpi B; /*!< 1. B in the equation, or 2. unused */ + ecp_point G; /*!< generator of the (sub)group used */ + mpi N; /*!< 1. the order of G, or 2. unused */ + size_t pbits; /*!< number of bits in P */ + size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ + unsigned int h; /*!< internal: 1 if the constants are static */ + int (*modp)(mpi *); /*!< function for fast reduction mod P */ + int (*t_pre)(ecp_point *, void *); /*!< unused */ + int (*t_post)(ecp_point *, void *); /*!< unused */ + void *t_data; /*!< unused */ + ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ + size_t T_size; /*!< number for pre-computed points */ +} +ecp_group; + +/** + * \brief ECP key pair structure + * + * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * + * \note Members purposefully in the same order as struc ecdsa_context. + */ +typedef struct +{ + ecp_group grp; /*!< Elliptic curve and base point */ + mpi d; /*!< our secret value */ + ecp_point Q; /*!< our public value */ +} +ecp_keypair; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_ECP_MAX_BITS) +/** + * Maximum size of the groups (that is, of N and P) + */ +#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#endif + +#define POLARSSL_ECP_MAX_BYTES ( ( POLARSSL_ECP_MAX_BITS + 7 ) / 8 ) +#define POLARSSL_ECP_MAX_PT_LEN ( 2 * POLARSSL_ECP_MAX_BYTES + 1 ) + +#if !defined(POLARSSL_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( POLARSSL_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#endif /* POLARSSL_ECP_WINDOW_SIZE */ + +#if !defined(POLARSSL_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#endif /* POLARSSL_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define POLARSSL_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ +#define POLARSSL_ECP_PF_COMPRESSED 1 /**< Compressed point format */ + +/* + * Some other constants from RFC 4492 + */ +#define POLARSSL_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ + +/** + * \brief Get the list of supported curves in order of preferrence + * (full information) + * + * \return A statically allocated array, the last entry is 0. + */ +const ecp_curve_info *ecp_curve_list( void ); + +/** + * \brief Get the list of supported curves in order of preferrence + * (grp_id only) + * + * \return A statically allocated array, + * terminated with POLARSSL_ECP_DP_NONE. + */ +const ecp_group_id *ecp_grp_id_list( void ); + +/** + * \brief Get curve information from an internal group identifier + * + * \param grp_id A POLARSSL_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id ); + +/** + * \brief Get curve information from a TLS NamedCurve value + * + * \param tls_id A POLARSSL_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief Get curve information from a human-readable name + * + * \param name The name + * + * \return The associated curve information or NULL + */ +const ecp_curve_info *ecp_curve_info_from_name( const char *name ); + +/** + * \brief Initialize a point (as zero) + */ +void ecp_point_init( ecp_point *pt ); + +/** + * \brief Initialize a group (to something meaningless) + */ +void ecp_group_init( ecp_group *grp ); + +/** + * \brief Initialize a key pair (as an invalid one) + */ +void ecp_keypair_init( ecp_keypair *key ); + +/** + * \brief Free the components of a point + */ +void ecp_point_free( ecp_point *pt ); + +/** + * \brief Free the components of an ECP group + */ +void ecp_group_free( ecp_group *grp ); + +/** + * \brief Free the components of a key pair + */ +void ecp_keypair_free( ecp_keypair *key ); + +/** + * \brief Copy the contents of point Q into P + * + * \param P Destination point + * \param Q Source point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int ecp_copy( ecp_point *P, const ecp_point *Q ); + +/** + * \brief Copy the contents of a group object + * + * \param dst Destination group + * \param src Source group + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int ecp_group_copy( ecp_group *dst, const ecp_group *src ); + +/** + * \brief Set a point to zero + * + * \param pt Destination point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int ecp_set_zero( ecp_point *pt ); + +/** + * \brief Tell if a point is zero + * + * \param pt Point to test + * + * \return 1 if point is zero, 0 otherwise + */ +int ecp_is_zero( ecp_point *pt ); + +/** + * \brief Import a non-zero point from two ASCII strings + * + * \param P Destination point + * \param radix Input numeric base + * \param x First affine coordinate as a null-terminated string + * \param y Second affine coordinate as a null-terminated string + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + */ +int ecp_point_read_string( ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief Export a point into unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to export + * \param format Point format, should be a POLARSSL_ECP_PF_XXX macro + * \param olen Length of the actual output + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, + * or POLARSSL_ERR_ECP_BAD_INPUT_DATA + * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL + */ +int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief Import a point from unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to import + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + * + * \note This function does NOT check that the point actually + * belongs to the given group, see ecp_check_pubkey() for + * that. + */ +int ecp_point_read_binary( const ecp_group *grp, ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief Import a point from a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Destination point + * \param buf $(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after the ECPoint on exit + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_XXX if initialization failed + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief Export a point as a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Point to export + * \param format Export format + * \param olen length of data written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or POLARSSL_ERR_ECP_BAD_INPUT_DATA + * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL + */ +int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Import an ECP group from null-terminated ASCII strings + * + * \param grp Destination group + * \param radix Input numeric base + * \param p Prime modulus of the base field + * \param b Constant term in the equation + * \param gx The generator's X coordinate + * \param gy The generator's Y coordinate + * \param n The generator's order + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + * + * \note Sets all fields except modp. + */ +int ecp_group_read_string( ecp_group *grp, int radix, + const char *p, const char *b, + const char *gx, const char *gy, const char *n); + +/** + * \brief Set a group using well-known domain parameters + * + * \param grp Destination group + * \param index Index in the list of well-known domain parameters + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_XXX if initialization failed + * POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * + * \note Index should be a value of RFC 4492's enum NamdeCurve, + * possibly in the form of a POLARSSL_ECP_DP_XXX macro. + */ +int ecp_use_known_dp( ecp_group *grp, ecp_group_id index ); + +/** + * \brief Set a group from a TLS ECParameters record + * + * \param grp Destination group + * \param buf &(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after ECParameters on exit + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_XXX if initialization failed + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len ); + +/** + * \brief Write the TLS ECParameters record for a group + * + * \param grp ECP group used + * \param olen Number of bytes actually written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL + */ +int ecp_tls_write_group( const ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Addition: R = P + Q + * + * \param grp ECP group + * \param R Destination point + * \param P Left-hand point + * \param Q Right-hand point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note This function does not support Montgomery curves, such as + * Curve25519. + */ +int ecp_add( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ); + +/** + * \brief Subtraction: R = P - Q + * + * \param grp ECP group + * \param R Destination point + * \param P Left-hand point + * \param Q Right-hand point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note This function does not support Montgomery curves, such as + * Curve25519. + */ +int ecp_sub( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ); + +/** + * \brief Multiplication by an integer: R = m * P + * (Not thread-safe to use same group in multiple threads) + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_INVALID_KEY if m is not a valid privkey + * or P is not a valid pubkey, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note In order to prevent timing attacks, this function + * executes the exact same sequence of (base field) + * operations for any valid m. It avoids any if-branch or + * array index depending on the value of m. + * + * \note If f_rng is not NULL, it is used to randomize intermediate + * results in order to prevent potential timing attacks + * targeting these results. It is recommended to always + * provide a non-NULL f_rng (the overhead is negligible). + */ +int ecp_mul( ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check that a point is a valid public key on this curve + * + * \param grp Curve/group the point should belong to + * \param pt Point to check + * + * \return 0 if point is a valid public key, + * POLARSSL_ERR_ECP_INVALID_KEY otherwise. + * + * \note This function only checks the point is non-zero, has valid + * coordinates and lies on the curve, but not that it is + * indeed a multiple of G. This is additional check is more + * expensive, isn't required by standards, and shouldn't be + * necessary if the group used has a small cofactor. In + * particular, it is useless for the NIST groups which all + * have a cofactor of 1. + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ); + +/** + * \brief Check that an mpi is a valid private key for this curve + * + * \param grp Group used + * \param d Integer to check + * + * \return 0 if point is a valid private key, + * POLARSSL_ERR_ECP_INVALID_KEY otherwise. + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_check_privkey( const ecp_group *grp, const mpi *d ); + +/** + * \brief Generate a keypair + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp_id ECP group identifier + * \param key Destination keypair + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check a public-private key pair + * + * \param pub Keypair structure holding a public key + * \param prv Keypair structure holding a private (plus public) key + * + * \return 0 if successful (keys are valid and match), or + * POLARSSL_ERR_ECP_BAD_INPUT_DATA, or + * a POLARSSL_ERR_ECP_XXX or POLARSSL_ERR_MPI_XXX code. + */ +int ecp_check_pub_priv( const ecp_keypair *pub, const ecp_keypair *prv ); + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int ecp_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/entropy.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/entropy.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,244 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ENTROPY_H +#define POLARSSL_ENTROPY_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256) +#include "sha512.h" +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(POLARSSL_SHA256_C) +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR +#include "sha256.h" +#endif +#endif + +#if defined(POLARSSL_THREADING_C) +#include "threading.h" +#endif + +#if defined(POLARSSL_HAVEGE_C) +#include "havege.h" +#endif + +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR -0x0058 /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(ENTROPY_MAX_SOURCES) +#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(ENTROPY_MAX_GATHER) +#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) +#define ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define ENTROPY_SOURCE_MANUAL ENTROPY_MAX_SOURCES + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct +{ + f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received */ + size_t threshold; /**< Minimum level required before release */ +} +source_state; + +/** + * \brief Entropy context structure + */ +typedef struct +{ +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_context accumulator; +#else + sha256_context accumulator; +#endif + int source_count; + source_state source[ENTROPY_MAX_SOURCES]; +#if defined(POLARSSL_HAVEGE_C) + havege_state havege_data; +#endif +#if defined(POLARSSL_THREADING_C) + threading_mutex_t mutex; /*!< mutex */ +#endif +} +entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void entropy_init( entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void entropy_free( entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with entropy_func() ) + * + * \return 0 if successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES + */ +int entropy_add_source( entropy_context *ctx, + f_source_ptr f_source, void *p_source, + size_t threshold ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_gather( entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: ENTROPY_BLOCK_SIZE) + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int entropy_update_manual( entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_write_seed_file( entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error, + * POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_update_seed_file( entropy_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int entropy_self_test( int verbose ); +#endif /* POLARSSL_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/entropy_poll.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/entropy_poll.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,77 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2011, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_POLL_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources + */ +#define ENTROPY_MIN_PLATFORM 128 /**< Minimum for platform source */ +#define ENTROPY_MIN_HAVEGE 128 /**< Minimum for HAVEGE */ +#define ENTROPY_MIN_HARDCLOCK 32 /**< Minimum for hardclock() */ + +#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(POLARSSL_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(POLARSSL_TIMING_C) +/** + * \brief hardclock-based entropy poll callback + */ +int hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/error.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/error.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,121 @@ +/** + * \file error.h + * + * \brief Error to string translation + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ERROR_H +#define POLARSSL_ERROR_H + +#include <stddef.h> + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bytes signed integers to support all platforms (-0x0000 - -0x8000). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Sign bit + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 2 0x0012-0x0014 + * BLOWFISH 2 0x0016-0x0018 + * THREADING 3 0x001A-0x001E + * AES 2 0x0020-0x0022 + * CAMELLIA 2 0x0024-0x0026 + * XTEA 1 0x0028-0x0028 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 1 0x0032-0x0032 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 + * NET 11 0x0042-0x0056 + * ENTROPY 1 0x0058-0x0058 + * ASN1 7 0x0060-0x006C + * MD2 1 0x0070-0x0070 + * MD4 1 0x0072-0x0072 + * MD5 1 0x0074-0x0074 + * SHA1 1 0x0076-0x0076 + * SHA256 1 0x0078-0x0078 + * SHA512 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * RIPEMD160 1 0x007E-0x007E + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 2 0x000D-0x000F + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 18 + * PK 2 14 (Started from top, plus 0x2000) + * DHM 3 9 + * PKCS5 3 4 (Started from top) + * RSA 4 9 + * ECP 4 8 (Started from top) + * MD 5 4 + * CIPHER 6 6 + * SSL 6 11 (Started from top) + * SSL 7 31 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void polarssl_strerror( int errnum, char *buffer, size_t buflen ); + +#if defined(POLARSSL_ERROR_STRERROR_BC) +void error_strerror( int errnum, char *buffer, size_t buflen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/gcm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/gcm.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,217 @@ +/** + * \file gcm.h + * + * \brief Galois/Counter mode for 128-bit block ciphers + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_GCM_H +#define POLARSSL_GCM_H + +#include "cipher.h" + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +#else +#include <stdint.h> +#endif + +#define GCM_ENCRYPT 1 +#define GCM_DECRYPT 0 + +#define POLARSSL_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ +#define POLARSSL_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief GCM context structure + */ +typedef struct { + cipher_context_t cipher_ctx;/*!< cipher context used */ + uint64_t HL[16]; /*!< Precalculated HTable */ + uint64_t HH[16]; /*!< Precalculated HTable */ + uint64_t len; /*!< Total data length */ + uint64_t add_len; /*!< Total add length */ + unsigned char base_ectr[16];/*!< First ECTR for tag */ + unsigned char y[16]; /*!< Y working value */ + unsigned char buf[16]; /*!< buf working value */ + int mode; /*!< Encrypt or Decrypt */ +} +gcm_context; + +/** + * \brief GCM initialization (encryption) + * + * \param ctx GCM context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or a cipher specific error code + */ +int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief GCM buffer encryption/decryption using a block cipher + * + * \note On encryption, the output buffer can be the same as the input buffer. + * On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param mode GCM_ENCRYPT or GCM_DECRYPT + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * \param tag_len length of the tag to generate + * \param tag buffer for holding the tag + * + * \return 0 if successful + */ +int gcm_crypt_and_tag( 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 ); + +/** + * \brief GCM buffer authenticated decryption using a block cipher + * + * \note On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param tag buffer holding the tag + * \param tag_len length of the tag + * \param input buffer holding the input data + * \param output buffer for holding the output data + * + * \return 0 if successful and authenticated, + * POLARSSL_ERR_GCM_AUTH_FAILED if tag does not match + */ +int gcm_auth_decrypt( 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 ); + +/** + * \brief Generic GCM stream start function + * + * \param ctx GCM context + * \param mode GCM_ENCRYPT or GCM_DECRYPT + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data (or NULL if length is 0) + * \param add_len length of additional data + * + * \return 0 if successful + */ +int gcm_starts( gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief Generic GCM update function. Encrypts/decrypts using the + * given GCM context. Expects input to be a multiple of 16 + * bytes! Only the last call before gcm_finish() can be less + * than 16 bytes! + * + * \note On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * + * \return 0 if successful or POLARSSL_ERR_GCM_BAD_INPUT + */ +int gcm_update( gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic GCM finalisation function. Wraps up the GCM stream + * and generates the tag. The tag can have a maximum length of + * 16 bytes. + * + * \param ctx GCM context + * \param tag buffer for holding the tag (may be NULL if tag_len is 0) + * \param tag_len length of the tag to generate + * + * \return 0 if successful or POLARSSL_ERR_GCM_BAD_INPUT + */ +int gcm_finish( gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief Free a GCM context and underlying cipher sub-context + * + * \param ctx GCM context to free + */ +void gcm_free( gcm_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int gcm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* gcm.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/havege.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/havege.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,76 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_HAVEGE_H +#define POLARSSL_HAVEGE_H + +#include <stddef.h> + +#define COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct +{ + int PT1, PT2, offset[2]; + int pool[COLLECT_SIZE]; + int WALK[8192]; +} +havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void havege_init( havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void havege_free( havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/hmac_drbg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/hmac_drbg.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,282 @@ +/** + * \file hmac_drbg.h + * + * \brief HMAC_DRBG (NIST SP 800-90A) + * + * Copyright (C) 2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_H + +#include "md.h" + +/* + * Error codes + */ +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_HMAC_DRBG_RESEED_INTERVAL) +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(POLARSSL_HMAC_DRBG_MAX_INPUT) +#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(POLARSSL_HMAC_DRBG_MAX_REQUEST) +#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(POLARSSL_HMAC_DRBG_MAX_SEED_INPUT) +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define POLARSSL_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define POLARSSL_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct +{ + /* Working state: the key K is not stored explicitely, + * but is implied by the HMAC context */ + md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[POLARSSL_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ +} hmac_drbg_context; + +/** + * \brief HMAC_DRBG initialisation + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \note The "security strength" as defined by NIST is set to: + * 128 bits if md_alg is SHA-1, + * 192 bits if md_alg is SHA-224, + * 256 bits if md_alg is SHA-256 or higher. + * Note that SHA-256 is just as efficient as SHA-224. + * + * \return 0 if successful, or + * POLARSSL_ERR_MD_BAD_INPUT_DATA, or + * POLARSSL_ERR_MD_ALLOC_FAILED, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED. + */ +int hmac_drbg_init( hmac_drbg_context *ctx, + const md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * (For use with deterministic ECDSA.) + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param data Concatenation of entropy string and additional data + * \param data_len Length of data in bytes + * + * \return 0 if successful, or + * POLARSSL_ERR_MD_BAD_INPUT_DATA, or + * POLARSSL_ERR_MD_ALLOC_FAILED. + */ +int hmac_drbg_init_buf( hmac_drbg_context *ctx, + const md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx HMAC_DRBG context + * \param resistance POLARSSL_HMAC_DRBG_PR_ON or POLARSSL_HMAC_DRBG_PR_OFF + */ +void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each reseed + * (Default: given by the security strength, which + * depends on the hash used, see \c hmac_drbg_init() ) + * + * \param ctx HMAC_DRBG context + * \param len Amount of entropy to grab, in bytes + */ +void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: POLARSSL_HMAC_DRBG_RESEED_INTERVAL) + * + * \param ctx HMAC_DRBG context + * \param interval Reseed interval + */ +void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, + int interval ); + +/** + * \brief HMAC_DRBG update state + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +void hmac_drbg_update( hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG reseeding (extracts data from entropy source) + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int hmac_drbg_reseed( hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief HMAC_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (can be NULL) + * \param add_len Length of additional data (can be 0) + * + * \return 0 if successful, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or + * POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG. + */ +int hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief HMAC_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param out_len Length of the buffer + * + * \return 0 if successful, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG + */ +int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx HMAC_DRBG context to free. + */ +void hmac_drbg_free( hmac_drbg_context *ctx ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or + * POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG + */ +int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ + + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/md.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/md.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,401 @@ +/** + * \file md.h + * + * \brief Generic message digest wrapper + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD_H +#define POLARSSL_MD_H + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define POLARSSL_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + POLARSSL_MD_NONE=0, + POLARSSL_MD_MD2, + POLARSSL_MD_MD4, + POLARSSL_MD_MD5, + POLARSSL_MD_SHA1, + POLARSSL_MD_SHA224, + POLARSSL_MD_SHA256, + POLARSSL_MD_SHA384, + POLARSSL_MD_SHA512, + POLARSSL_MD_RIPEMD160, +} md_type_t; + +#if defined(POLARSSL_SHA512_C) +#define POLARSSL_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define POLARSSL_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Message digest information. Allows message digest functions to be called + * in a generic way. + */ +typedef struct { + /** Digest identifier */ + md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function */ + int size; + + /** Digest initialisation function */ + void (*starts_func)( void *ctx ); + + /** Digest update function */ + void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + void (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + void (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Generic file digest function */ + int (*file_func)( const char *path, unsigned char *output ); + + /** HMAC Initialisation function */ + void (*hmac_starts_func)( void *ctx, const unsigned char *key, + size_t keylen ); + + /** HMAC update function */ + void (*hmac_update_func)( void *ctx, const unsigned char *input, + size_t ilen ); + + /** HMAC finalisation function */ + void (*hmac_finish_func)( void *ctx, unsigned char *output); + + /** HMAC context reset function */ + void (*hmac_reset_func)( void *ctx ); + + /** Generic HMAC function */ + void (*hmac_func)( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Internal use only */ + void (*process_func)( void *ctx, const unsigned char *input ); +} md_info_t; + +/** + * Generic message digest context. + */ +typedef struct { + /** Information about the associated message digest */ + const md_info_t *md_info; + + /** Digest-specific context */ + void *md_ctx; +} md_context_t; + +#define MD_CONTEXT_T_INIT { \ + NULL, /* md_info */ \ + NULL, /* md_ctx */ \ +} + +/** + * \brief Returns the list of digests supported by the generic digest module. + * + * \return a statically allocated array of digests, the last entry + * is 0. + */ +const int *md_list( void ); + +/** + * \brief Returns the message digest information associated with the + * given digest name. + * + * \param md_name Name of the digest to search for. + * + * \return The message digest information associated with md_name or + * NULL if not found. + */ +const md_info_t *md_info_from_string( const char *md_name ); + +/** + * \brief Returns the message digest information associated with the + * given digest type. + * + * \param md_type type of digest to search for. + * + * \return The message digest information associated with md_type or + * NULL if not found. + */ +const md_info_t *md_info_from_type( md_type_t md_type ); + +/** + * \brief Initialize a md_context (as NONE) + */ +void md_init( md_context_t *ctx ); + +/** + * \brief Free and clear the message-specific context of ctx. + * Freeing ctx itself remains the responsibility of the + * caller. + */ +void md_free( md_context_t *ctx ); + +/** + * \brief Initialises and fills the message digest context structure + * with the appropriate values. + * + * \note Currently also clears structure. In future versions you + * will be required to call md_init() on the structure + * first. + * + * \param ctx context to initialise. May not be NULL. The + * digest-specific context (ctx->md_ctx) must be NULL. It will + * be allocated, and must be freed using md_free_ctx() later. + * \param md_info message digest to use. + * + * \returns \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on + * parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if + * allocation of the digest-specific context failed. + */ +int md_init_ctx( md_context_t *ctx, const md_info_t *md_info ); + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +#if defined(POLARSSL_DEPRECATED_WARNING) +#define DEPRECATED __attribute__((deprecated)) +#else +#define DEPRECATED +#endif +/** + * \brief Free the message-specific context of ctx. Freeing ctx itself + * remains the responsibility of the caller. + * + * \deprecated Use md_free() instead + * + * \param ctx Free the message-specific context + * + * \returns 0 + */ +int md_free_ctx( md_context_t *ctx ) DEPRECATED; +#undef DEPRECATED +#endif /* POLARSSL_DEPRECATED_REMOVED */ + +/** + * \brief Returns the size of the message digest output. + * + * \param md_info message digest info + * + * \return size of the message digest output. + */ +static inline unsigned char md_get_size( const md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +/** + * \brief Returns the type of the message digest output. + * + * \param md_info message digest info + * + * \return type of the message digest output. + */ +static inline md_type_t md_get_type( const md_info_t *md_info ) +{ + if( md_info == NULL ) + return( POLARSSL_MD_NONE ); + + return md_info->type; +} + +/** + * \brief Returns the name of the message digest output. + * + * \param md_info message digest info + * + * \return name of the message digest output. + */ +static inline const char *md_get_name( const md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +/** + * \brief Set-up the given context for a new message digest + * + * \param ctx generic message digest context. + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_starts( md_context_t *ctx ); + +/** + * \brief Generic message digest process buffer + * + * \param ctx Generic message digest context + * \param input buffer holding the datal + * \param ilen length of the input data + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief Generic message digest final digest + * + * \param ctx Generic message digest context + * \param output Generic message digest checksum result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_finish( md_context_t *ctx, unsigned char *output ); + +/** + * \brief Output = message_digest( input buffer ) + * + * \param md_info message digest info + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic message digest checksum result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md( const md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +/** + * \brief Output = message_digest( file contents ) + * + * \param md_info message digest info + * \param path input file name + * \param output generic message digest checksum result + * + * \return 0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen + * failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed, + * POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL. + */ +int md_file( const md_info_t *md_info, const char *path, + unsigned char *output ); + +/** + * \brief Generic HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_starts( md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief Generic HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_update( md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief Generic HMAC final digest + * + * \param ctx HMAC context + * \param output Generic HMAC checksum result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_finish( md_context_t *ctx, unsigned char *output); + +/** + * \brief Generic HMAC context reset + * + * \param ctx HMAC context to be reset + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_reset( md_context_t *ctx ); + +/** + * \brief Output = Generic_HMAC( hmac key, input buffer ) + * + * \param md_info message digest info + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic HMAC-result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int md_process( md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_MD_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/md2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/md2.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,192 @@ +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD2_H +#define POLARSSL_MD2_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#define POLARSSL_ERR_MD2_FILE_IO_ERROR -0x0070 /**< Read/write error in file. */ + +#if !defined(POLARSSL_MD2_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD2 context structure + */ +typedef struct +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + + unsigned char ipad[16]; /*!< HMAC: inner padding */ + unsigned char opad[16]; /*!< HMAC: outer padding */ + size_t left; /*!< amount of data in buffer */ +} +md2_context; + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + */ +void md2_init( md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + */ +void md2_free( md2_context *ctx ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + */ +void md2_starts( md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + */ +void md2_finish( md2_context *ctx, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_MD2_ALT */ +#include "md2_alt.h" +#endif /* POLARSSL_MD2_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + */ +void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Output = MD2( file contents ) + * + * \param path input file name + * \param output MD2 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_MD2_FILE_IO_ERROR + */ +int md2_file( const char *path, unsigned char output[16] ); + +/** + * \brief MD2 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void md2_hmac_starts( md2_context *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief MD2 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md2_hmac_update( md2_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 HMAC final digest + * + * \param ctx HMAC context + * \param output MD2 HMAC checksum result + */ +void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ); + +/** + * \brief MD2 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void md2_hmac_reset( md2_context *ctx ); + +/** + * \brief Output = HMAC-MD2( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-MD2 result + */ +void md2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int md2_self_test( int verbose ); + +/* Internal use */ +void md2_process( md2_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* md2.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/md4.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/md4.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,198 @@ +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD4_H +#define POLARSSL_MD4_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define POLARSSL_ERR_MD4_FILE_IO_ERROR -0x0072 /**< Read/write error in file. */ + +#if !defined(POLARSSL_MD4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +md4_context; + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + */ +void md4_init( md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + */ +void md4_free( md4_context *ctx ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + */ +void md4_starts( md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_MD4_ALT */ +#include "md4_alt.h" +#endif /* POLARSSL_MD4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + */ +void md4( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Output = MD4( file contents ) + * + * \param path input file name + * \param output MD4 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_MD4_FILE_IO_ERROR + */ +int md4_file( const char *path, unsigned char output[16] ); + +/** + * \brief MD4 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void md4_hmac_starts( md4_context *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief MD4 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_hmac_update( md4_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 HMAC final digest + * + * \param ctx HMAC context + * \param output MD4 HMAC checksum result + */ +void md4_hmac_finish( md4_context *ctx, unsigned char output[16] ); + +/** + * \brief MD4 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void md4_hmac_reset( md4_context *ctx ); + +/** + * \brief Output = HMAC-MD4( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-MD4 result + */ +void md4_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int md4_self_test( int verbose ); + +/* Internal use */ +void md4_process( md4_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#endif /* md4.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/md5.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/md5.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,198 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD5_H +#define POLARSSL_MD5_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define POLARSSL_ERR_MD5_FILE_IO_ERROR -0x0074 /**< Read/write error in file. */ + +#if !defined(POLARSSL_MD5_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +md5_context; + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + */ +void md5_init( md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + */ +void md5_free( md5_context *ctx ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void md5_starts( md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ); + +/* Internal use */ +void md5_process( md5_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_MD5_ALT */ +#include "md5_alt.h" +#endif /* POLARSSL_MD5_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Output = MD5( file contents ) + * + * \param path input file name + * \param output MD5 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_MD5_FILE_IO_ERROR + */ +int md5_file( const char *path, unsigned char output[16] ); + +/** + * \brief MD5 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void md5_hmac_starts( md5_context *ctx, + const unsigned char *key, size_t keylen ); + +/** + * \brief MD5 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_hmac_update( md5_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief MD5 HMAC final digest + * + * \param ctx HMAC context + * \param output MD5 HMAC checksum result + */ +void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ); + +/** + * \brief MD5 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void md5_hmac_reset( md5_context *ctx ); + +/** + * \brief Output = HMAC-MD5( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-MD5 result + */ +void md5_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int md5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* md5.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/md_wrap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/md_wrap.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,70 @@ +/** + * \file md_wrap.h + * + * \brief Message digest wrappers. + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2011, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD_WRAP_H +#define POLARSSL_MD_WRAP_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(POLARSSL_MD2_C) +extern const md_info_t md2_info; +#endif +#if defined(POLARSSL_MD4_C) +extern const md_info_t md4_info; +#endif +#if defined(POLARSSL_MD5_C) +extern const md_info_t md5_info; +#endif +#if defined(POLARSSL_RIPEMD160_C) +extern const md_info_t ripemd160_info; +#endif +#if defined(POLARSSL_SHA1_C) +extern const md_info_t sha1_info; +#endif +#if defined(POLARSSL_SHA256_C) +extern const md_info_t sha224_info; +extern const md_info_t sha256_info; +#endif +#if defined(POLARSSL_SHA512_C) +extern const md_info_t sha384_info; +extern const md_info_t sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_MD_WRAP_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/memory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/memory.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,63 @@ +/** + * \file memory.h + * + * \brief Memory allocation layer + * + * \deprecated Use the platform layer instead + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MEMORY_H +#define POLARSSL_MEMORY_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stdlib.h> + +#include "platform.h" +#include "memory_buffer_alloc.h" + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +#if defined(POLARSSL_DEPRECATED_WARNING) +#define DEPRECATED __attribute__((deprecated)) +#else +#define DEPRECATED +#endif +/** + * \brief Set malloc() / free() callback + * + * \deprecated Use platform_set_malloc_free instead + */ +int memory_set_own( void * (*malloc_func)( size_t ), + void (*free_func)( void * ) ) DEPRECATED; +int memory_set_own( void * (*malloc_func)( size_t ), + void (*free_func)( void * ) ) +{ + return platform_set_malloc_free( malloc_func, free_func ); +} +#undef DEPRECATED +#endif /* POLARSSL_DEPRECATED_REMOVED */ + + +#endif /* memory.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/memory_buffer_alloc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/memory_buffer_alloc.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,150 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_MEMORY_ALIGN_MULTIPLE) +#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MEMORY_VERIFY_NONE 0 +#define MEMORY_VERIFY_ALLOC (1 << 0) +#define MEMORY_VERIFY_FREE (1 << 1) +#define MEMORY_VERIFY_ALWAYS (MEMORY_VERIFY_ALLOC | MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call malloc() and free(). + * It sets the global polarssl_malloc() and polarssl_free() pointers + * to its own functions. + * (Provided polarssl_malloc() and polarssl_free() are thread-safe if + * POLARSSL_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + * + * \return 0 if successful + */ +int memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MEMORY_VERIFY_NONE) + * + * \param verify One of MEMORY_VERIFY_NONE, MEMORY_VERIFY_ALLOC, + * MEMORY_VERIFY_FREE or MEMORY_VERIFY_ALWAYS + */ +void memory_buffer_set_verify( int verify ); + +#if defined(POLARSSL_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if POLARSSL_MEMORY_BACKTRACE is defined. + */ +void memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes reauested by the application + * \param max_blocks Peak number of blocks reauested by the application + */ +void memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Number of bytes reauested by the application + * \param cur_blocks Number of blocks reauested by the application + */ +void memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* POLARSSL_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if POLARSSL_MEMORY_DEBUG is defined. + * Prints out full header information if POLARSSL_MEMORY_DEBUG_HEADERS + * is defined. (Includes stack trace information for each block if + * POLARSSL_MEMORY_BACKTRACE is defined as well). + * + * \returns 0 if verified, 1 otherwise + */ +int memory_buffer_alloc_verify( void ); + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/net.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/net.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,158 @@ +/** + * \file net.h + * + * \brief Network communication functions + * + * Copyright (C) 2006-2011, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_NET_H +#define POLARSSL_NET_H + +#include <stddef.h> + +#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */ +#define POLARSSL_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define POLARSSL_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define POLARSSL_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define POLARSSL_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define POLARSSL_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define POLARSSL_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define POLARSSL_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define POLARSSL_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define POLARSSL_ERR_NET_WANT_READ -0x0052 /**< Connection requires a read call. */ +#define POLARSSL_ERR_NET_WANT_WRITE -0x0054 /**< Connection requires a write call. */ + +#define POLARSSL_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initiate a TCP connection with host:port + * + * \param fd Socket to use + * \param host Host to connect to + * \param port Port to connect to + * + * \return 0 if successful, or one of: + * POLARSSL_ERR_NET_SOCKET_FAILED, + * POLARSSL_ERR_NET_UNKNOWN_HOST, + * POLARSSL_ERR_NET_CONNECT_FAILED + */ +int net_connect( int *fd, const char *host, int port ); + +/** + * \brief Create a listening socket on bind_ip:port. + * If bind_ip == NULL, all interfaces are binded. + * + * \param fd Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * + * \return 0 if successful, or one of: + * POLARSSL_ERR_NET_SOCKET_FAILED, + * POLARSSL_ERR_NET_BIND_FAILED, + * POLARSSL_ERR_NET_LISTEN_FAILED + */ +int net_bind( int *fd, const char *bind_ip, int port ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_fd Relevant socket + * \param client_fd Will contain the connected client socket + * \param client_ip Will contain the client IP address + * Must be at least 4 bytes, or 16 if IPv6 is supported + * + * \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or + * POLARSSL_ERR_NET_WANT_READ is bind_fd was set to + * non-blocking and accept() is blocking. + */ +int net_accept( int bind_fd, int *client_fd, void *client_ip ); + +/** + * \brief Set the socket blocking + * + * \param fd Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int net_set_block( int fd ); + +/** + * \brief Set the socket non-blocking + * + * \param fd Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int net_set_nonblock( int fd ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return This function returns the number of bytes received, + * or a non-zero error code; POLARSSL_ERR_NET_WANT_READ + * indicates read() is blocking. + */ +int net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return This function returns the number of bytes sent, + * or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE + * indicates write() is blocking. + */ +int net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Gracefully shutdown the connection + * + * \param fd The socket to close + */ +void net_close( int fd ); + +#ifdef __cplusplus +} +#endif + +#endif /* net.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/oid.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/oid.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,572 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_OID_H +#define POLARSSL_OID_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#include <stddef.h> + +#if defined(POLARSSL_CIPHER_C) +#include "cipher.h" +#endif + +#if defined(POLARSSL_MD_C) +#include "md.h" +#endif + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "x509.h" +#endif + +#define POLARSSL_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define POLARSSL_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define OID_RSA_COMPANY OID_ISO_MEMBER_BODIES OID_COUNTRY_US \ + OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define OID_ANSI_X9_62 OID_ISO_MEMBER_BODIES OID_COUNTRY_US \ + OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define OID_ORG_DOD "\x06" /* {dod(6)} */ +#define OID_ORG_OIW "\x0e" +#define OID_OIW_SECSIG OID_ORG_OIW "\x03" +#define OID_OIW_SECSIG_ALG OID_OIW_SECSIG "\x02" +#define OID_OIW_SECSIG_SHA1 OID_OIW_SECSIG_ALG "\x1a" +#define OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define OID_CERTICOM OID_ISO_IDENTIFIED_ORG OID_ORG_CERTICOM +#define OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define OID_TELETRUST OID_ISO_IDENTIFIED_ORG OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define OID_ISO_ITU_US_ORG OID_ISO_ITU_COUNTRY OID_COUNTRY_US OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define OID_ORG_GOV "\x65" /* {gov(101)} */ +#define OID_GOV OID_ISO_ITU_US_ORG OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define OID_NETSCAPE OID_ISO_ITU_US_ORG OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define OID_ID_CE OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define OID_PKIX OID_ISO_IDENTIFIED_ORG OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define OID_AT OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define OID_AT_CN OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define OID_AT_SUR_NAME OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define OID_AT_SERIAL_NUMBER OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define OID_AT_COUNTRY OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define OID_AT_LOCALITY OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define OID_AT_STATE OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define OID_AT_ORGANIZATION OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define OID_AT_ORG_UNIT OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define OID_AT_TITLE OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define OID_AT_POSTAL_ADDRESS OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define OID_AT_POSTAL_CODE OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define OID_AT_GIVEN_NAME OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define OID_AT_INITIALS OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define OID_AT_GENERATION_QUALIFIER OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define OID_AT_UNIQUE_IDENTIFIER OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define OID_AT_DN_QUALIFIER OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define OID_AT_PSEUDONYM OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define OID_AUTHORITY_KEY_IDENTIFIER OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define OID_SUBJECT_KEY_IDENTIFIER OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define OID_KEY_USAGE OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define OID_CERTIFICATE_POLICIES OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define OID_POLICY_MAPPINGS OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define OID_SUBJECT_ALT_NAME OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define OID_ISSUER_ALT_NAME OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define OID_SUBJECT_DIRECTORY_ATTRS OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define OID_BASIC_CONSTRAINTS OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define OID_NAME_CONSTRAINTS OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define OID_POLICY_CONSTRAINTS OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define OID_EXTENDED_KEY_USAGE OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define OID_CRL_DISTRIBUTION_POINTS OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define OID_INIHIBIT_ANYPOLICY OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define OID_FRESHEST_CRL OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define OID_NS_CERT OID_NETSCAPE "\x01" +#define OID_NS_CERT_TYPE OID_NS_CERT "\x01" +#define OID_NS_BASE_URL OID_NS_CERT "\x02" +#define OID_NS_REVOCATION_URL OID_NS_CERT "\x03" +#define OID_NS_CA_REVOCATION_URL OID_NS_CERT "\x04" +#define OID_NS_RENEWAL_URL OID_NS_CERT "\x07" +#define OID_NS_CA_POLICY_URL OID_NS_CERT "\x08" +#define OID_NS_SSL_SERVER_NAME OID_NS_CERT "\x0C" +#define OID_NS_COMMENT OID_NS_CERT "\x0D" +#define OID_NS_DATA_TYPE OID_NETSCAPE "\x02" +#define OID_NS_CERT_SEQUENCE OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define OID_PRIVATE_KEY_USAGE_PERIOD OID_ID_CE "\x10" +#define OID_CRL_NUMBER OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define OID_ANY_EXTENDED_KEY_USAGE OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define OID_KP OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define OID_SERVER_AUTH OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define OID_CLIENT_AUTH OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define OID_CODE_SIGNING OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define OID_EMAIL_PROTECTION OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define OID_TIME_STAMPING OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define OID_OCSP_SIGNING OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define OID_PKCS OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define OID_PKCS1 OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define OID_PKCS5 OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define OID_PKCS9 OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define OID_PKCS12 OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define OID_PKCS1_RSA OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define OID_PKCS1_MD2 OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define OID_PKCS1_MD4 OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define OID_PKCS1_MD5 OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define OID_PKCS1_SHA1 OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define OID_PKCS1_SHA224 OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define OID_PKCS1_SHA256 OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define OID_PKCS1_SHA384 OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define OID_PKCS1_SHA512 OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define OID_PKCS9_EMAIL OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define OID_RSASSA_PSS OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define OID_MGF1 OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define OID_DIGEST_ALG_MD2 OID_RSA_COMPANY "\x02\x02" /**< id-md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define OID_DIGEST_ALG_MD4 OID_RSA_COMPANY "\x02\x04" /**< id-md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define OID_DIGEST_ALG_MD5 OID_RSA_COMPANY "\x02\x05" /**< id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define OID_DIGEST_ALG_SHA1 OID_ISO_IDENTIFIED_ORG OID_OIW_SECSIG_SHA1 /**< id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define OID_DIGEST_ALG_SHA224 OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define OID_DIGEST_ALG_SHA256 OID_GOV "\x03\x04\x02\x01" /**< id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define OID_DIGEST_ALG_SHA384 OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define OID_DIGEST_ALG_SHA512 OID_GOV "\x03\x04\x02\x03" /**< id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define OID_HMAC_SHA1 OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +/* + * Encryption algorithms + */ +#define OID_DES_CBC OID_ISO_IDENTIFIED_ORG OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define OID_DES_EDE3_CBC OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ + +/* + * PKCS#5 OIDs + */ +#define OID_PKCS5_PBKDF2 OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define OID_PKCS5_PBES2 OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define OID_PKCS5_PBMAC1 OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define OID_PKCS5_PBE_MD2_DES_CBC OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define OID_PKCS5_PBE_MD2_RC2_CBC OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define OID_PKCS5_PBE_MD5_DES_CBC OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define OID_PKCS5_PBE_MD5_RC2_CBC OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define OID_PKCS5_PBE_SHA1_DES_CBC OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define OID_PKCS5_PBE_SHA1_RC2_CBC OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define OID_PKCS9_CSR_EXT_REQ OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define OID_PKCS12_PBE OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define OID_PKCS12_PBE_SHA1_RC4_128 OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define OID_PKCS12_PBE_SHA1_RC4_40 OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define OID_EC_ALG_UNRESTRICTED OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define OID_EC_ALG_ECDH OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define OID_EC_GRP_SECP192R1 OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define OID_EC_GRP_SECP224R1 OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define OID_EC_GRP_SECP256R1 OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define OID_EC_GRP_SECP384R1 OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define OID_EC_GRP_SECP521R1 OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define OID_EC_GRP_SECP192K1 OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define OID_EC_GRP_SECP224K1 OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define OID_EC_GRP_SECP256K1 OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define OID_EC_BRAINPOOL_V1 OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define OID_EC_GRP_BP256R1 OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define OID_EC_GRP_BP384R1 OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define OID_EC_GRP_BP512R1 OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define OID_ANSI_X9_62_FIELD_TYPE OID_ANSI_X9_62 "\x01" +#define OID_ANSI_X9_62_PRIME_FIELD OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define OID_ANSI_X9_62_SIG OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define OID_ANSI_X9_62_SIG_SHA2 OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define OID_ECDSA_SHA1 OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define OID_ECDSA_SHA224 OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define OID_ECDSA_SHA256 OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define OID_ECDSA_SHA384 OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define OID_ECDSA_SHA512 OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct { + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * POLARSSL_ERR_OID_BUF_TOO_SMALL in case of error + */ +int oid_get_numeric_string( char *buf, size_t size, const asn1_buf *oid ); + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_x509_ext_type( const asn1_buf *oid, int *ext_type ); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_attr_short_name( const asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_pk_alg( pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(POLARSSL_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_ec_grp( const asn1_buf *oid, ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_ec_grp( ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_sig_alg( const asn1_buf *oid, + md_type_t *md_alg, pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_sig_alg_desc( const asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_sig_alg( pk_type_t pk_alg, md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_md_alg( const asn1_buf *oid, md_type_t *md_alg ); +#endif /* POLARSSL_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_extended_key_usage( const asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_md( md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(POLARSSL_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_cipher_alg( const asn1_buf *oid, cipher_type_t *cipher_alg ); +#endif /* POLARSSL_CIPHER_C */ + +#if defined(POLARSSL_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_pkcs12_pbe_alg( const asn1_buf *oid, md_type_t *md_alg, + cipher_type_t *cipher_alg ); +#endif /* POLARSSL_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/openssl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/openssl.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,149 @@ +/** + * \file openssl.h + * + * \brief OpenSSL wrapper (definitions, inline functions). + * + * \deprecated Use native mbed TLS functions instead + * + * Copyright (C) 2006-2010, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * OpenSSL wrapper contributed by David Barett + */ + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) + +#if defined(POLARSSL_DEPRECATED_WARNING) +#warning "Including openssl.h is deprecated" +#endif + +#ifndef POLARSSL_OPENSSL_H +#define POLARSSL_OPENSSL_H + +#include "aes.h" +#include "md5.h" +#include "rsa.h" +#include "sha1.h" + +#define AES_SIZE 16 +#define AES_BLOCK_SIZE 16 +#define AES_KEY aes_context +#define MD5_CTX md5_context +#define SHA_CTX sha1_context + +#define SHA1_Init( CTX ) \ + sha1_starts( (CTX) ) +#define SHA1_Update( CTX, BUF, LEN ) \ + sha1_update( (CTX), (unsigned char *)(BUF), (LEN) ) +#define SHA1_Final( OUT, CTX ) \ + sha1_finish( (CTX), (OUT) ) + +#define MD5_Init( CTX ) \ + md5_starts( (CTX) ) +#define MD5_Update( CTX, BUF, LEN ) \ + md5_update( (CTX), (unsigned char *)(BUF), (LEN) ) +#define MD5_Final( OUT, CTX ) \ + md5_finish( (CTX), (OUT) ) + +#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \ + aes_setkey_enc( (CTX), (KEY), (KEYSIZE) ) +#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \ + aes_setkey_dec( (CTX), (KEY), (KEYSIZE) ) +#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \ + aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * RSA stuff follows. TODO: needs cleanup + */ +inline int __RSA_Passthrough( void *output, void *input, int size ) +{ + memcpy( output, input, size ); + return size; +} + +inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr, + int len ) +{ + unsigned char *buffer = *(unsigned char **) bufptr; + rsa_context *rsa; + + /* + * Not a general-purpose parser: only parses public key from *exactly* + * openssl genrsa -out privkey.pem 512 (or 1024) + * openssl rsa -in privkey.pem -out privatekey.der -outform der + * openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout + * + * TODO: make a general-purpose parse + */ + if( ignore != 0 || ( len != 94 && len != 162 ) ) + return( 0 ); + + rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) ); + if( rsa == NULL ) + return( 0 ); + + memset( rsa, 0, sizeof( rsa_context ) ); + + if( ( len == 94 && + mpi_read_binary( &rsa->N, &buffer[ 25], 64 ) == 0 && + mpi_read_binary( &rsa->E, &buffer[ 91], 3 ) == 0 ) || + ( len == 162 && + mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) && + mpi_read_binary( &rsa->E, &buffer[159], 3 ) == 0 ) + { + /* + * key read successfully + */ + rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3; + return( rsa ); + } + else + { + memset( rsa, 0, sizeof( rsa_context ) ); + free( rsa ); + return( 0 ); + } +} + +#define RSA rsa_context +#define RSA_PKCS1_PADDING 1 /* ignored; always encrypt with this */ +#define RSA_size( CTX ) (CTX)->len +#define RSA_free( CTX ) rsa_free( CTX ) +#define ERR_get_error( ) "ERR_get_error() not supported" +#define RSA_blinding_off( IGNORE ) + +#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */ + +inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC, &outsize, input, output ) ) return outsize; else return -1; } +inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; } +inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC, size, input, output ) ) return RSA_size(key); else return -1; } +inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; } + +#ifdef __cplusplus +} +#endif + +#endif /* openssl.h */ +#endif /* POLARSSL_DEPRECATED_REMOVED */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/padlock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/padlock.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,106 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PADLOCK_H +#define POLARSSL_PADLOCK_H + +#include "aes.h" + +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) + +#ifndef POLARSSL_HAVE_X86 +#define POLARSSL_HAVE_X86 +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef INT32 int32_t; +#else +#include <inttypes.h> +#endif + +#define PADLOCK_RNG 0x000C +#define PADLOCK_ACE 0x00C0 +#define PADLOCK_PHE 0x0C00 +#define PADLOCK_PMM 0x3000 + +#define PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PadLock detection routine + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int padlock_supports( int feature ); + +/** + * \brief PadLock AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int padlock_xcryptecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief PadLock AES-CBC buffer en(de)cryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int padlock_xcryptcbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/pbkdf2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/pbkdf2.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,91 @@ +/** + * \file pbkdf2.h + * + * \brief Password-Based Key Derivation Function 2 (from PKCS#5) + * + * \deprecated Use pkcs5.h instead. + * + * \author Mathias Olsson <mathias@kompetensum.com> + * + * Copyright (C) 2006-2012, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PBKDF2_H +#define POLARSSL_PBKDF2_H + +#include "md.h" + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA -0x007C /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +#if defined(POLARSSL_DEPRECATED_WARNING) +#define DEPRECATED __attribute__((deprecated)) +#else +#define DEPRECATED +#endif +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \deprecated Use pkcs5_pbkdf2_hmac() instead + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a POLARSSL_ERR_xxx code if verification fails. + */ +int pbkdf2_hmac( 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 ) DEPRECATED; + +/** + * \brief Checkup routine + * + * \deprecated Use pkcs5_self_test() instead + * + * \return 0 if successful, or 1 if the test failed + */ +int pbkdf2_self_test( int verbose ) DEPRECATED; +#undef DEPRECATED +#endif /* POLARSSL_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#endif /* pbkdf2.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/pem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/pem.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,131 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PEM_H +#define POLARSSL_PEM_H + +#include <stddef.h> + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define POLARSSL_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define POLARSSL_ERR_PEM_MALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(POLARSSL_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void pem_init( pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * POLARSSL_ERR_PEM_BAD_INPUT_DATA or + * POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void pem_free( pem_context *ctx ); +#endif /* POLARSSL_PEM_PARSE_C */ + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header header string to write + * \param footer footer string to write + * \param der_data DER data to write + * \param der_len length of the DER data + * \param buf buffer to write to + * \param buf_len length of output buffer + * \param olen total length written / required (if buf_len is not enough) + * + * \return 0 on success, or a specific PEM or BASE64 error code. On + * POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL olen is the required + * size. + */ +int 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 ); +#endif /* POLARSSL_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/pk.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/pk.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,651 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef POLARSSL_PK_H +#define POLARSSL_PK_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(POLARSSL_RSA_C) +#include "rsa.h" +#endif + +#if defined(POLARSSL_ECP_C) +#include "ecp.h" +#endif + +#if defined(POLARSSL_ECDSA_C) +#include "ecdsa.h" +#endif + +#define POLARSSL_ERR_PK_MALLOC_FAILED -0x2F80 /**< Memory alloation failed. */ +#define POLARSSL_ERR_PK_TYPE_MISMATCH -0x2F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define POLARSSL_ERR_PK_BAD_INPUT_DATA -0x2E80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_PK_FILE_IO_ERROR -0x2E00 /**< Read/write of file failed. */ +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION -0x2D80 /**< Unsupported key version */ +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT -0x2D00 /**< Invalid key tag or value. */ +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG -0x2C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED -0x2C00 /**< Private key password can't be empty. */ +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH -0x2B80 /**< Given private key password does not allow for correct decryption. */ +#define POLARSSL_ERR_PK_INVALID_PUBKEY -0x2B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define POLARSSL_ERR_PK_INVALID_ALG -0x2A80 /**< The algorithm tag or value is invalid. */ +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE -0x2A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE -0x2980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH -0x2000 /**< The signature is valid but its length is less than expected. */ + + +#if defined(POLARSSL_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this macro! + */ +#define pk_rsa( pk ) ( (rsa_context *) (pk).pk_ctx ) +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this macro! + */ +#define pk_ec( pk ) ( (ecp_keypair *) (pk).pk_ctx ) +#endif /* POLARSSL_ECP_C */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + POLARSSL_PK_NONE=0, + POLARSSL_PK_RSA, + POLARSSL_PK_ECKEY, + POLARSSL_PK_ECKEY_DH, + POLARSSL_PK_ECDSA, + POLARSSL_PK_RSA_ALT, + POLARSSL_PK_RSASSA_PSS, +} pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c rsa_rsassa_pss_verify_ext() + */ +typedef struct +{ + md_type_t mgf1_hash_id; + int expected_salt_len; + +} pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + POLARSSL_PK_DEBUG_NONE = 0, + POLARSSL_PK_DEBUG_MPI, + POLARSSL_PK_DEBUG_ECP, +} pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct +{ + pk_debug_type type; + const char *name; + void *value; +} pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define POLARSSL_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct +{ + /** Public key type */ + pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_size)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, 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 ); + + /** Decrypt message */ + int (*decrypt_func)( 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 ); + + /** Encrypt message */ + int (*encrypt_func)( 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 ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, pk_debug_item *items ); + +} pk_info_t; + +/** + * \brief Public key container + */ +typedef struct +{ + const pk_info_t * pk_info; /**< Public key informations */ + void * pk_ctx; /**< Underlying public key context */ +} pk_context; + +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*pk_rsa_alt_key_len_func)( void *ctx ); + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const pk_info_t *pk_info_from_type( pk_type_t pk_type ); + +/** + * \brief Initialize a pk_context (as NONE) + */ +void pk_init( pk_context *ctx ); + +/** + * \brief Free a pk_context + */ +void pk_free( pk_context *ctx ); + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param info Information to use + * + * \return 0 on success, + * POLARSSL_ERR_PK_BAD_INPUT_DATA on invalid input, + * POLARSSL_ERR_PK_MALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c pk_init_ctx_rsa_alt() instead. + */ +int pk_init_ctx( pk_context *ctx, const pk_info_t *info ); + +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or POLARSSL_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c pk_init_ctx() for RSA-alt. + */ +int pk_init_ctx_rsa_alt( pk_context *ctx, void * key, + pk_rsa_alt_decrypt_func decrypt_func, + pk_rsa_alt_sign_func sign_func, + pk_rsa_alt_key_len_func key_len_func ); + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx Context to use + * + * \return Key size in bits, or 0 on error + */ +size_t pk_get_size( const pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * \param ctx Context to use + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t pk_get_len( const pk_context *ctx ) +{ + return( ( pk_get_size( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx Context to test + * \param type Target type + * + * \return 0 if context can't do the operations, + * 1 otherwise. + */ +int pk_can_do( pk_context *ctx, pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c pk_verify_ext( POLARSSL_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 + */ +int pk_verify( pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * POLARSSL_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 + * + * \note If type is POLARSSL_PK_RSASSA_PSS, then options must point + * to a pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int pk_verify_ext( pk_type_t type, const void *options, + pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 + */ +int pk_sign( pk_context *ctx, 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 ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int pk_decrypt( 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 ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int pk_encrypt( 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 ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return 0 on success or POLARSSL_ERR_PK_BAD_INPUT_DATA + */ +int pk_check_pair( const pk_context *pub, const pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx Context to use + * \param items Place to write debug items + * + * \return 0 on success or POLARSSL_ERR_PK_BAD_INPUT_DATA + */ +int pk_debug( const pk_context *ctx, pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx Context to use + * + * \return Type name on success, or "invalid PK" + */ +const char * pk_get_name( const pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx Context to use + * + * \return Type on success, or POLARSSL_PK_NONE + */ +pk_type_t pk_get_type( const pk_context *ctx ); + +#if defined(POLARSSL_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_key( pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_public_key( pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(POLARSSL_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_keyfile( pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_public_keyfile( pk_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ +#endif /* POLARSSL_PK_PARSE_C */ + +#if defined(POLARSSL_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int pk_write_key_der( pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int pk_write_pubkey_der( pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int pk_write_pubkey_pem( pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int pk_write_key_pem( pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(POLARSSL_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk the key to fill + * + * \return 0 if successful, or a specific PK error code + */ +int pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + pk_context *pk ); +#endif /* POLARSSL_PK_PARSE_C */ + +#if defined(POLARSSL_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key public key to write away + * + * \return the length written or a negative error code + */ +int pk_write_pubkey( unsigned char **p, unsigned char *start, + const pk_context *key ); +#endif /* POLARSSL_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(POLARSSL_FS_IO) +int pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_PK_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/pk_wrap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/pk_wrap.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,61 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer: wrapper functions + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef POLARSSL_PK_WRAP_H +#define POLARSSL_PK_WRAP_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "pk.h" + +/* Container for RSA-alt */ +typedef struct +{ + void *key; + pk_rsa_alt_decrypt_func decrypt_func; + pk_rsa_alt_sign_func sign_func; + pk_rsa_alt_key_len_func key_len_func; +} rsa_alt_context; + +#if defined(POLARSSL_RSA_C) +extern const pk_info_t rsa_info; +#endif + +#if defined(POLARSSL_ECP_C) +extern const pk_info_t eckey_info; +extern const pk_info_t eckeydh_info; +#endif + +#if defined(POLARSSL_ECDSA_C) +extern const pk_info_t ecdsa_info; +#endif + +extern const pk_info_t rsa_alt_info; + +#endif /* POLARSSL_PK_WRAP_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/pkcs11.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/pkcs11.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,172 @@ +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PKCS11_H +#define POLARSSL_PKCS11_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PKCS11_C) + +#include "x509_crt.h" + +#include <pkcs11-helper-1.0/pkcs11h-certificate.h> + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context for PKCS #11 private keys. + */ +typedef struct { + pkcs11h_certificate_t pkcs11h_cert; + int len; +} pkcs11_context; + +/** + * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Initialise a pkcs11_context, storing the given certificate. Note that the + * pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +int pkcs11_priv_key_init( pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \param priv_key Private key structure to cleanup + */ +void pkcs11_priv_key_free( pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \param ctx PKCS #11 context + * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int pkcs11_decrypt( pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \param ctx PKCS #11 context + * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int pkcs11_sign( pkcs11_context *ctx, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + */ +static inline int ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return pkcs11_decrypt( (pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +static inline int ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return pkcs11_sign( (pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +static inline size_t ssl_pkcs11_key_len( void *ctx ) +{ + return ( (pkcs11_context *) ctx )->len; +} + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_PKCS11_C */ + +#endif /* POLARSSL_PKCS11_H */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/pkcs12.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/pkcs12.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,121 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PKCS12_H +#define POLARSSL_PKCS12_H + +#include "md.h" +#include "cipher.h" +#include "asn1.h" + +#include <stddef.h> + +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define PKCS12_PBE_DECRYPT 0 +#define PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either PKCS12_PBE_ENCRYPT or PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a POLARSSL_ERR_xxx code + */ +int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either PKCS12_PBE_ENCRYPT or PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a POLARSSL_ERR_xxx code + */ +int pkcs12_pbe( asn1_buf *pbe_params, int mode, + cipher_type_t cipher_type, md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param md md type to use during the derivation + * \param id id that describes the purpose (can be PKCS12_DERIVE_KEY, + * PKCS12_DERIVE_IV or PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + md_type_t md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/pkcs5.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/pkcs5.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,102 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson <mathias@kompetensum.com> + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PKCS5_H +#define POLARSSL_PKCS5_H + +#include "asn1.h" +#include "md.h" + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA -0x3f80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT -0x3f00 /**< Unexpected ASN.1 data. */ +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE -0x3e80 /**< Requested encryption or digest alg not available. */ +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH -0x3e00 /**< Given private key password does not allow for correct decryption. */ + +#define PKCS5_DECRYPT 0 +#define PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either PKCS5_DECRYPT or PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a POLARSSL_ERR_xxx code if verification fails. + */ +int pkcs5_pbes2( asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a POLARSSL_ERR_xxx code if verification fails. + */ +int pkcs5_pbkdf2_hmac( 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 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int pkcs5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/platform.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/platform.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,206 @@ +/** + * \file platform.h + * + * \brief mbed TLS Platform abstraction layer + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PLATFORM_H +#define POLARSSL_PLATFORM_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +/* Temporary compatibility hack for to keep MEMORY_C working */ +#if defined(POLARSSL_MEMORY_C) && !defined(POLARSSL_PLATFORM_MEMORY) +#define POLARSSL_PLATFORM_MEMORY +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS) +#include <stdio.h> +#include <stdlib.h> +#if !defined(POLARSSL_PLATFORM_STD_SNPRINTF) +#define POLARSSL_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_PRINTF) +#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_FPRINTF) +#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_MALLOC) +#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_FREE) +#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_EXIT) +#define POLARSSL_PLATFORM_STD_EXIT exit /**< Default free to use */ +#endif +#else /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(POLARSSL_PLATFORM_STD_MEM_HDR) +#include POLARSSL_PLATFORM_STD_MEM_HDR +#endif +#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */ + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for malloc and free + */ +#if defined(POLARSSL_PLATFORM_MEMORY) +#if defined(POLARSSL_PLATFORM_FREE_MACRO) && \ + defined(POLARSSL_PLATFORM_MALLOC_MACRO) +#define polarssl_free POLARSSL_PLATFORM_FREE_MACRO +#define polarssl_malloc POLARSSL_PLATFORM_MALLOC_MACRO +#else +/* For size_t */ +#include <stddef.h> +extern void * (*polarssl_malloc)( size_t len ); +extern void (*polarssl_free)( void *ptr ); + +/** + * \brief Set your own memory implementation function pointers + * + * \param malloc_func the malloc function implementation + * \param free_func the free function implementation + * + * \return 0 if successful + */ +int platform_set_malloc_free( void * (*malloc_func)( size_t ), + void (*free_func)( void * ) ); +#endif /* POLARSSL_PLATFORM_FREE_MACRO && POLARSSL_PLATFORM_MALLOC_MACRO */ +#else /* !POLARSSL_PLATFORM_MEMORY */ +#define polarssl_free free +#define polarssl_malloc malloc +#endif /* POLARSSL_PLATFORM_MEMORY && !POLARSSL_PLATFORM_{FREE,MALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include <stdio.h> +extern int (*polarssl_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief Set your own fprintf function pointer + * + * \param fprintf_func the fprintf function implementation + * + * \return 0 + */ +int platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(POLARSSL_PLATFORM_FPRINTF_MACRO) +#define polarssl_fprintf POLARSSL_PLATFORM_FPRINTF_MACRO +#else +#define polarssl_fprintf fprintf +#endif /* POLARSSL_PLATFORM_FPRINTF_MACRO */ +#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(POLARSSL_PLATFORM_PRINTF_ALT) +extern int (*polarssl_printf)( const char *format, ... ); + +/** + * \brief Set your own printf function pointer + * + * \param printf_func the printf function implementation + * + * \return 0 + */ +int platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !POLARSSL_PLATFORM_PRINTF_ALT */ +#if defined(POLARSSL_PLATFORM_PRINTF_MACRO) +#define polarssl_printf POLARSSL_PLATFORM_PRINTF_MACRO +#else +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_PRINTF_MACRO */ +#endif /* POLARSSL_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + */ +#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT) +extern int (*polarssl_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief Set your own snprintf function pointer + * + * \param snprintf_func the snprintf function implementation + * + * \return 0 + */ +int platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* POLARSSL_PLATFORM_SNPRINTF_ALT */ +#if defined(POLARSSL_PLATFORM_SNPRINTF_MACRO) +#define polarssl_snprintf POLARSSL_PLATFORM_SNPRINTF_MACRO +#else +#define polarssl_snprintf snprintf +#endif /* POLARSSL_PLATFORM_SNPRINTF_MACRO */ +#endif /* POLARSSL_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(POLARSSL_PLATFORM_EXIT_ALT) +extern void (*polarssl_exit)( int status ); + +/** + * \brief Set your own exit function pointer + * + * \param exit_func the exit function implementation + * + * \return 0 + */ +int platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(POLARSSL_PLATFORM_EXIT_MACRO) +#define polarssl_exit POLARSSL_PLATFORM_EXIT_MACRO +#else +#define polarssl_exit exit +#endif /* POLARSSL_PLATFORM_EXIT_MACRO */ +#endif /* POLARSSL_PLATFORM_EXIT_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ripemd160.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ripemd160.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,202 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + * + * Copyright (C) 2014-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_RIPEMD160_H +#define POLARSSL_RIPEMD160_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR -0x007E /**< Read/write error in file. */ + +#if !defined(POLARSSL_RIPEMD160_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +ripemd160_context; + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void ripemd160_init( ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void ripemd160_free( ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + */ +void ripemd160_starts( ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void ripemd160_update( ripemd160_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +void ripemd160_finish( ripemd160_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void ripemd160_process( ripemd160_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_RIPEMD160_ALT */ +#include "ripemd160.h" +#endif /* POLARSSL_RIPEMD160_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +void ripemd160( const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Output = RIPEMD-160( file contents ) + * + * \param path input file name + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR + */ +int ripemd160_file( const char *path, unsigned char output[20] ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief RIPEMD-160 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void ripemd160_hmac_starts( ripemd160_context *ctx, + const unsigned char *key, size_t keylen ); + +/** + * \brief RIPEMD-160 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void ripemd160_hmac_update( ripemd160_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief RIPEMD-160 HMAC final digest + * + * \param ctx HMAC context + * \param output RIPEMD-160 HMAC checksum result + */ +void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] ); + +/** + * \brief RIPEMD-160 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void ripemd160_hmac_reset( ripemd160_context *ctx ); + +/** + * \brief Output = HMAC-RIPEMD-160( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-RIPEMD-160 result + */ +void ripemd160_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ripemd160_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* ripemd160.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/rsa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/rsa.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,654 @@ +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_RSA_H +#define POLARSSL_RSA_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "bignum.h" +#include "md.h" + +#if defined(POLARSSL_THREADING_C) +#include "threading.h" +#endif + +/* + * RSA Error codes + */ +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the library's validity check. */ +#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* + * RSA constants + */ +#define RSA_PUBLIC 0 +#define RSA_PRIVATE 1 + +#define RSA_PKCS_V15 0 +#define RSA_PKCS_V21 1 + +#define RSA_SIGN 1 +#define RSA_CRYPT 2 + +#define RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ +#if defined(POLARSSL_RSA_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RSA context structure + */ +typedef struct +{ + int ver; /*!< always 0 */ + size_t len; /*!< size(N) in chars */ + + mpi N; /*!< public modulus */ + mpi E; /*!< public exponent */ + + mpi D; /*!< private exponent */ + mpi P; /*!< 1st prime factor */ + mpi Q; /*!< 2nd prime factor */ + mpi DP; /*!< D % (P - 1) */ + mpi DQ; /*!< D % (Q - 1) */ + mpi QP; /*!< 1 / (Q % P) */ + + mpi RN; /*!< cached R^2 mod N */ + mpi RP; /*!< cached R^2 mod P */ + mpi RQ; /*!< cached R^2 mod Q */ + + mpi Vi; /*!< cached blinding value */ + mpi Vf; /*!< cached un-blinding value */ + + int padding; /*!< RSA_PKCS_V15 for 1.5 padding and + RSA_PKCS_v21 for OAEP/PSS */ + int hash_id; /*!< Hash identifier of md_type_t as + specified in the md.h header file + for the EME-OAEP and EMSA-PSS + encoding */ +#if defined(POLARSSL_THREADING_C) + threading_mutex_t mutex; /*!< Thread-safety mutex */ +#endif +} +rsa_context; + +/** + * \brief Initialize an RSA context + * + * Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx RSA context to be initialized + * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 + * \param hash_id RSA_PKCS_V21 hash identifier + * + * \note The hash_id parameter is actually ignored + * when using RSA_PKCS_V15 padding. + * + * \note Choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it's merely + * a default value, which can be overriden by calling specific + * rsa_rsaes_xxx or rsa_rsassa_xxx functions. + * + * \note The chosen hash is always used for OEAP encryption. + * For PSS signatures, it's always used for making signatures, + * but can be overriden (and always is, if set to + * POLARSSL_MD_NONE) for verifying them. + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief Set padding for an already initialized RSA context + * See \c rsa_init() for details. + * + * \param ctx RSA context to be set + * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 + * \param hash_id RSA_PKCS_V21 hash identifier + */ +void rsa_set_padding( rsa_context *ctx, int padding, int hash_id); + +/** + * \brief Generate an RSA keypair + * + * \param ctx RSA context that will hold the key + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param nbits size of the public key in bits + * \param exponent public exponent (e.g., 65537) + * + * \note rsa_init() must be called beforehand to setup + * the RSA context. + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_gen_key( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief Check a public RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_pubkey( const rsa_context *ctx ); + +/** + * \brief Check a private RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_privkey( const rsa_context *ctx ); + +/** + * \brief Check a public-private RSA key pair. + * Check each of the contexts, and make sure they match. + * + * \param pub RSA context holding the public key + * \param prv RSA context holding the private key + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_pub_priv( const rsa_context *pub, const rsa_context *prv ); + +/** + * \brief Do an RSA public key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note This function does NOT take care of message + * padding. Also, be sure to set input[0] = 0 or assure that + * input is smaller than N. + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Do an RSA private key operation + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for blinding) + * \param p_rng RNG parameter + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_private( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic wrapper to perform a PKCS#1 encryption using the + * mode from the context. Add the message padding, then do an + * RSA operation. + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding + * and RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_pkcs1_encrypt( 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 ); + +/** + * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_pkcs1_v15_encrypt( 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 ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding + * and RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_oaep_encrypt( 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 ); + +/** + * \brief Generic wrapper to perform a PKCS#1 decryption using the + * mode from the context. Do an RSA operation, then remove + * the message padding + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_pkcs1_decrypt( 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 ); + +/** + * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_pkcs1_v15_decrypt( 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 ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_oaep_decrypt( 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 ); + +/** + * \brief Generic wrapper to perform a PKCS#1 signature using the + * mode from the context. Do a private RSA operation to sign + * a message digest + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for + * RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding, see comments on + * \note \c rsa_rsassa_pss_sign() for details on md_alg and hash_id. + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for + * RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is the one used for the + * encoding. md_alg in the function call is the type of hash + * that is encoded. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_rsassa_pss_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Generic wrapper to perform a PKCS#1 verification using the + * mode from the context. Do a public RSA operation and check + * the message digest + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding, see comments on + * \c rsa_rsassa_pss_verify() about md_alg and hash_id. + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * (This is the "simple" version.) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is the one used for the + * verification. md_alg in the function call is the type of + * hash that is verified. According to RFC 3447 it is advised to + * keep both hashes the same. If hash_id in the RSA context is + * unset, the md_alg from the function call is used. + */ +int rsa_rsassa_pss_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * (This is the version with "full" options.) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param mgf1_hash_id message digest used for mask generation + * \param expected_salt_len Length of the salt used in padding, use + * RSA_SALT_LEN_ANY to accept any salt length + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is ignored. + */ +int rsa_rsassa_pss_verify_ext( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief Copy the components of an RSA context + * + * \param dst Destination context + * \param src Source context + * + * \return O on success, + * POLARSSL_ERR_MPI_MALLOC_FAILED on memory allocation failure + */ +int rsa_copy( rsa_context *dst, const rsa_context *src ); + +/** + * \brief Free the components of an RSA key + * + * \param ctx RSA Context to free + */ +void rsa_free( rsa_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_RSA_C */ + +#endif /* rsa.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/sha1.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/sha1.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,198 @@ +/** + * \file sha1.h + * + * \brief SHA-1 cryptographic hash function + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA1_H +#define POLARSSL_SHA1_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ + +#if !defined(POLARSSL_SHA1_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +sha1_context; + +/** + * \brief Initialize SHA-1 context + * + * \param ctx SHA-1 context to be initialized + */ +void sha1_init( sha1_context *ctx ); + +/** + * \brief Clear SHA-1 context + * + * \param ctx SHA-1 context to be cleared + */ +void sha1_free( sha1_context *ctx ); + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void sha1_process( sha1_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* POLARSSL_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( file contents ) + * + * \param path input file name + * \param output SHA-1 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR + */ +int sha1_file( const char *path, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief SHA-1 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-1 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-1 HMAC checksum result + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha1_hmac_reset( sha1_context *ctx ); + +/** + * \brief Output = HMAC-SHA-1( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-1 result + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha1.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/sha256.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/sha256.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,206 @@ +/** + * \file sha256.h + * + * \brief SHA-224 and SHA-256 cryptographic hash function + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA256_H +#define POLARSSL_SHA256_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define POLARSSL_ERR_SHA256_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */ + +#if !defined(POLARSSL_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-256 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} +sha256_context; + +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +void sha256_init( sha256_context *ctx ); + +/** + * \brief Clear SHA-256 context + * + * \param ctx SHA-256 context to be cleared + */ +void sha256_free( sha256_context *ctx ); + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256_starts( sha256_context *ctx, int is224 ); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha256_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +void sha256_finish( sha256_context *ctx, unsigned char output[32] ); + +/* Internal use */ +void sha256_process( sha256_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* POLARSSL_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-256( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Output = SHA-256( file contents ) + * + * \param path input file name + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + * + * \return 0 if successful, or POLARSSL_ERR_SHA256_FILE_IO_ERROR + */ +int sha256_file( const char *path, unsigned char output[32], int is224 ); + +/** + * \brief SHA-256 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key, + size_t keylen, int is224 ); + +/** + * \brief SHA-256 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha256_hmac_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-256 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-224/256 HMAC checksum result + */ +void sha256_hmac_finish( sha256_context *ctx, unsigned char output[32] ); + +/** + * \brief SHA-256 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha256_hmac_reset( sha256_context *ctx ); + +/** + * \brief Output = HMAC-SHA-256( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-224/256 result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha256.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/sha512.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/sha512.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,205 @@ +/** + * \file sha512.h + * + * \brief SHA-384 and SHA-512 cryptographic hash function + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA512_H +#define POLARSSL_SHA512_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) || defined(__WATCOMC__) + typedef unsigned __int64 uint64_t; +#else + #include <inttypes.h> +#endif + +#define POLARSSL_ERR_SHA512_FILE_IO_ERROR -0x007A /**< Read/write error in file. */ + +#if !defined(POLARSSL_SHA512_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-512 context structure + */ +typedef struct +{ + uint64_t total[2]; /*!< number of bytes processed */ + uint64_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[128]; /*!< data block being processed */ + + unsigned char ipad[128]; /*!< HMAC: inner padding */ + unsigned char opad[128]; /*!< HMAC: outer padding */ + int is384; /*!< 0 => SHA-512, else SHA-384 */ +} +sha512_context; + +/** + * \brief Initialize SHA-512 context + * + * \param ctx SHA-512 context to be initialized + */ +void sha512_init( sha512_context *ctx ); + +/** + * \brief Clear SHA-512 context + * + * \param ctx SHA-512 context to be cleared + */ +void sha512_free( sha512_context *ctx ); + +/** + * \brief SHA-512 context setup + * + * \param ctx context to be initialized + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void sha512_starts( sha512_context *ctx, int is384 ); + +/** + * \brief SHA-512 process buffer + * + * \param ctx SHA-512 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha512_update( sha512_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-512 final digest + * + * \param ctx SHA-512 context + * \param output SHA-384/512 checksum result + */ +void sha512_finish( sha512_context *ctx, unsigned char output[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* POLARSSL_SHA512_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-512( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-384/512 checksum result + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void sha512( const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ); + +/** + * \brief Output = SHA-512( file contents ) + * + * \param path input file name + * \param output SHA-384/512 checksum result + * \param is384 0 = use SHA512, 1 = use SHA384 + * + * \return 0 if successful, or POLARSSL_ERR_SHA512_FILE_IO_ERROR + */ +int sha512_file( const char *path, unsigned char output[64], int is384 ); + +/** + * \brief SHA-512 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param is384 0 = use SHA512, 1 = use SHA384 + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key, + size_t keylen, int is384 ); + +/** + * \brief SHA-512 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha512_hmac_update( sha512_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-512 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-384/512 HMAC checksum result + */ +void sha512_hmac_finish( sha512_context *ctx, unsigned char output[64] ); + +/** + * \brief SHA-512 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha512_hmac_reset( sha512_context *ctx ); + +/** + * \brief Output = HMAC-SHA-512( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-384/512 result + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void sha512_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha512_self_test( int verbose ); + +/* Internal use */ +void sha512_process( sha512_context *ctx, const unsigned char data[128] ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha512.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ssl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ssl.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,2009 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SSL_H +#define POLARSSL_SSL_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +/* Temporary compatibility trick for the current stable branch */ +#if !defined(POLARSSL_SSL_DISABLE_RENEGOTIATION) +#define POLARSSL_SSL_RENEGOTIATION +#endif + +#include "net.h" +#include "bignum.h" +#include "ecp.h" + +#include "ssl_ciphersuites.h" + +#if defined(POLARSSL_MD5_C) +#include "md5.h" +#endif + +#if defined(POLARSSL_SHA1_C) +#include "sha1.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#include "sha256.h" +#endif + +#if defined(POLARSSL_SHA512_C) +#include "sha512.h" +#endif + +// for session tickets +#if defined(POLARSSL_AES_C) +#include "aes.h" +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +#include "x509_crt.h" +#include "x509_crl.h" +#endif + +#if defined(POLARSSL_DHM_C) +#include "dhm.h" +#endif + +#if defined(POLARSSL_ECDH_C) +#include "ecdh.h" +#endif + +#if defined(POLARSSL_ZLIB_SUPPORT) +#include "zlib.h" +#endif + +#if defined(POLARSSL_HAVE_TIME) +#include <time.h> +#endif + +/* For convenience below and in programs */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#endif + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +/* + * SSL Error codes + */ +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define POLARSSL_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define POLARSSL_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define POLARSSL_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define POLARSSL_ERR_SSL_MALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define POLARSSL_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6A80 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ + +/* + * Various constants + */ +#define SSL_MAJOR_VERSION_3 3 +#define SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +/* Determine minimum supported version */ +#define SSL_MIN_MAJOR_VERSION SSL_MAJOR_VERSION_3 + +#if defined(POLARSSL_SSL_PROTO_SSL3) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_0 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_1 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1_1) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_2 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_3 +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#endif /* POLARSSL_SSL_PROTO_TLS1_1 */ +#endif /* POLARSSL_SSL_PROTO_TLS1 */ +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +/* Determine maximum supported version */ +#define SSL_MAX_MAJOR_VERSION SSL_MAJOR_VERSION_3 + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_3 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1_1) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_2 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_1 +#else +#if defined(POLARSSL_SSL_PROTO_SSL3) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_0 +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#endif /* POLARSSL_SSL_PROTO_TLS1 */ +#endif /* POLARSSL_SSL_PROTO_TLS1_1 */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define SSL_IS_CLIENT 0 +#define SSL_IS_SERVER 1 + +#define SSL_IS_NOT_FALLBACK 0 +#define SSL_IS_FALLBACK 1 + +#define SSL_EXTENDED_MS_DISABLED 0 +#define SSL_EXTENDED_MS_ENABLED 1 + +#define SSL_ETM_DISABLED 0 +#define SSL_ETM_ENABLED 1 + +#define SSL_COMPRESS_NULL 0 +#define SSL_COMPRESS_DEFLATE 1 + +#define SSL_VERIFY_NONE 0 +#define SSL_VERIFY_OPTIONAL 1 +#define SSL_VERIFY_REQUIRED 2 + +#define SSL_INITIAL_HANDSHAKE 0 +#define SSL_RENEGOTIATION 1 /* In progress */ +#define SSL_RENEGOTIATION_DONE 2 /* Done */ +#define SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +#define SSL_LEGACY_RENEGOTIATION 0 +#define SSL_SECURE_RENEGOTIATION 1 + +#define SSL_RENEGOTIATION_DISABLED 0 +#define SSL_RENEGOTIATION_ENABLED 1 + +#define SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define SSL_LEGACY_NO_RENEGOTIATION 0 +#define SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define SSL_TRUNC_HMAC_DISABLED 0 +#define SSL_TRUNC_HMAC_ENABLED 1 +#define SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define SSL_SESSION_TICKETS_DISABLED 0 +#define SSL_SESSION_TICKETS_ENABLED 1 + +#define SSL_CBC_RECORD_SPLITTING_DISABLED -1 +#define SSL_CBC_RECORD_SPLITTING_ENABLED 0 + +#define SSL_ARC4_ENABLED 0 +#define SSL_ARC4_DISABLED 1 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(SSL_DEFAULT_TICKET_LIFETIME) +#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Size of the input / output buffer. + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(SSL_MAX_CONTENT_LEN) +#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +/* \} name SECTION: Module settings */ + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(POLARSSL_ZLIB_SUPPORT) +#define SSL_COMPRESSION_ADD 1024 +#else +#define SSL_COMPRESSION_ADD 0 +#endif + +#if defined(POLARSSL_RC4_C) || defined(POLARSSL_CIPHER_MODE_CBC) +/* Ciphersuites using HMAC */ +#if defined(POLARSSL_SHA512_C) +#define SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(POLARSSL_SHA256_C) +#define SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define SSL_MAC_ADD 16 +#endif + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#define SSL_PADDING_ADD 256 +#else +#define SSL_PADDING_ADD 0 +#endif + +#define SSL_BUFFER_LEN ( SSL_MAX_CONTENT_LEN \ + + SSL_COMPRESSION_ADD \ + + 29 /* counter + header + IV */ \ + + SSL_MAC_ADD \ + + SSL_PADDING_ADD \ + ) + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) +#define SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define SSL_FALLBACK_SCSV 0x5600 /**< draft-ietf-tls-downgrade-scsv-00 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define SSL_HASH_NONE 0 +#define SSL_HASH_MD5 1 +#define SSL_HASH_SHA1 2 +#define SSL_HASH_SHA224 3 +#define SSL_HASH_SHA256 4 +#define SSL_HASH_SHA384 5 +#define SSL_HASH_SHA512 6 + +#define SSL_SIG_ANON 0 +#define SSL_SIG_RSA 1 +#define SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define SSL_CERT_TYPE_RSA_SIGN 1 +#define SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define SSL_MSG_ALERT 21 +#define SSL_MSG_HANDSHAKE 22 +#define SSL_MSG_APPLICATION_DATA 23 + +#define SSL_ALERT_LEVEL_WARNING 1 +#define SSL_ALERT_LEVEL_FATAL 2 + +#define SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define SSL_HS_HELLO_REQUEST 0 +#define SSL_HS_CLIENT_HELLO 1 +#define SSL_HS_SERVER_HELLO 2 +#define SSL_HS_NEW_SESSION_TICKET 4 +#define SSL_HS_CERTIFICATE 11 +#define SSL_HS_SERVER_KEY_EXCHANGE 12 +#define SSL_HS_CERTIFICATE_REQUEST 13 +#define SSL_HS_SERVER_HELLO_DONE 14 +#define SSL_HS_CERTIFICATE_VERIFY 15 +#define SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define TLS_EXT_SERVERNAME 0 +#define TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define TLS_EXT_TRUNCATED_HMAC 4 + +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define TLS_EXT_SIG_ALG 13 + +#define TLS_EXT_ALPN 16 + +#define TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define TLS_EXT_SESSION_TICKET 35 + +#define TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) + +/* + * Size defines + */ +#if !defined(POLARSSL_PSK_MAX_LEN) +#define POLARSSL_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union _ssl_premaster_secret +{ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[POLARSSL_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[POLARSSL_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * POLARSSL_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + POLARSSL_MPI_MAX_SIZE + + POLARSSL_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + POLARSSL_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + POLARSSL_ECP_MAX_BYTES + + POLARSSL_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +}; + +#define POLARSSL_PREMASTER_SIZE sizeof( union _ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Generic function pointers for allowing external RSA private key + * implementations. + */ +typedef int (*rsa_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*rsa_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*rsa_key_len_func)( void *ctx ); + +/* + * SSL state machine + */ +typedef enum +{ + SSL_HELLO_REQUEST, + SSL_CLIENT_HELLO, + SSL_SERVER_HELLO, + SSL_SERVER_CERTIFICATE, + SSL_SERVER_KEY_EXCHANGE, + SSL_CERTIFICATE_REQUEST, + SSL_SERVER_HELLO_DONE, + SSL_CLIENT_CERTIFICATE, + SSL_CLIENT_KEY_EXCHANGE, + SSL_CERTIFICATE_VERIFY, + SSL_CLIENT_CHANGE_CIPHER_SPEC, + SSL_CLIENT_FINISHED, + SSL_SERVER_CHANGE_CIPHER_SPEC, + SSL_SERVER_FINISHED, + SSL_FLUSH_BUFFERS, + SSL_HANDSHAKE_WRAPUP, + SSL_HANDSHAKE_OVER, + SSL_SERVER_NEW_SESSION_TICKET, +} +ssl_states; + +typedef struct _ssl_session ssl_session; +typedef struct _ssl_context ssl_context; +typedef struct _ssl_transform ssl_transform; +typedef struct _ssl_handshake_params ssl_handshake_params; +#if defined(POLARSSL_SSL_SESSION_TICKETS) +typedef struct _ssl_ticket_keys ssl_ticket_keys; +#endif +#if defined(POLARSSL_X509_CRT_PARSE_C) +typedef struct _ssl_key_cert ssl_key_cert; +#endif + +/* + * This structure is used for storing current session data. + */ +struct _ssl_session +{ +#if defined(POLARSSL_HAVE_TIME) + time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t length; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) + x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#endif /* POLARSSL_X509_CRT_PARSE_C */ + int verify_result; /*!< verification result */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct _ssl_transform +{ + /* + * Session specific crypto layer + */ + const ssl_ciphersuite_t *ciphersuite_info; + /*!< Chosen cipersuite_info */ + unsigned int keylen; /*!< symmetric key length */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + + md_context_t md_ctx_enc; /*!< MAC (encryption) */ + md_context_t md_ctx_dec; /*!< MAC (decryption) */ + + cipher_context_t cipher_ctx_enc; /*!< encryption context */ + cipher_context_t cipher_ctx_dec; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(POLARSSL_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct _ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + int sig_alg; /*!< Hash algorithm for signature */ + int cert_type; /*!< Requested cert type */ + int verify_sig_alg; /*!< Signature algorithm for verify */ +#if defined(POLARSSL_DHM_C) + dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(POLARSSL_ECDH_C) + ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + const ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(POLARSSL_X509_CRT_PARSE_C) + /** + * Current key/cert or key/cert list. + * On client: pointer to ssl->key_cert, only the first entry used. + * On server: starts as a pointer to ssl->key_cert, then becomes + * a pointer to the chosen key from this list or the SNI list. + */ + ssl_key_cert *key_cert; +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ +#endif +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + /* + * Checksum contexts + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + md5_context fin_md5; + sha1_context fin_sha1; +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) + sha256_context fin_sha256; +#endif +#if defined(POLARSSL_SHA512_C) + sha512_context fin_sha512; +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + void (*update_checksum)(ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(ssl_context *, unsigned char *); + void (*calc_finished)(ssl_context *, unsigned char *, int); + int (*tls_prf)(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[POLARSSL_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* POLARSSL_SSL_SESSION_TICKETS */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif +}; + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/* + * Parameters needed to secure session tickets + */ +struct _ssl_ticket_keys +{ + unsigned char key_name[16]; /*!< name to quickly discard bad tickets */ + aes_context enc; /*!< encryption context */ + aes_context dec; /*!< decryption context */ + unsigned char mac_key[16]; /*!< authentication key */ +}; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct _ssl_key_cert +{ + x509_crt *cert; /*!< cert */ + pk_context *key; /*!< private key */ + int key_own_alloc; /*!< did we allocate key? */ + ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +struct _ssl_context +{ + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ + int renegotiation; /*!< Initial or renegotiation */ +#if defined(POLARSSL_SSL_RENEGOTIATION) + int renego_records_seen; /*!< Records since renego request */ +#endif + + int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + + int max_major_ver; /*!< max. major version used */ + int max_minor_ver; /*!< max. minor version used */ + int min_major_ver; /*!< min. major version used */ + int min_minor_ver; /*!< min. minor version used */ + +#if defined(POLARSSL_SSL_FALLBACK_SCSV) && defined(POLARSSL_SSL_CLI_C) + char fallback; /*!< flag for fallback connections */ +#endif +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + char encrypt_then_mac; /*!< flag for encrypt-then-mac */ +#endif +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + char extended_ms; /*!< flag for extended master secret */ +#endif + char arc4_disabled; /*!< flag for disabling RC4 */ + + /* + * Callbacks (RNG, debug, I/O, verification) + */ + int (*f_rng)(void *, unsigned char *, size_t); + void (*f_dbg)(void *, int, const char *); + int (*f_recv)(void *, unsigned char *, size_t); + int (*f_send)(void *, const unsigned char *, size_t); + int (*f_get_cache)(void *, ssl_session *); + int (*f_set_cache)(void *, const ssl_session *); + + void *p_rng; /*!< context for the RNG function */ + void *p_dbg; /*!< context for the debug function */ + void *p_recv; /*!< context for reading operations */ + void *p_send; /*!< context for writing operations */ + void *p_get_cache; /*!< context for cache retrieval */ + void *p_set_cache; /*!< context for cache store */ + void *p_hw_data; /*!< context for HW acceleration */ + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + int (*f_sni)(void *, ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI extension */ +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + int (*f_vrfy)(void *, x509_crt *, int, int *); + void *p_vrfy; /*!< context for verification */ +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + int (*f_psk)(void *, ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK retrieval */ +#endif + + /* + * Session layer + */ + ssl_session *session_in; /*!< current session data (in) */ + ssl_session *session_out; /*!< current session data (out) */ + ssl_session *session; /*!< negotiated session data */ + ssl_session *session_negotiate; /*!< session data in negotiation */ + + ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + ssl_transform *transform_in; /*!< current transform params (in) */ + ssl_transform *transform_out; /*!< current transform params (in) */ + ssl_transform *transform; /*!< negotiated transform params */ + ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter */ + unsigned char *in_hdr; /*!< 5-byte record header (in_ctr+8) */ + unsigned char *in_iv; /*!< ivlen-byte IV (in_hdr+5) */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ + + size_t in_hslen; /*!< current handshake message length */ + int nb_zero; /*!< # of 0-length encrypted messages */ + int record_read; /*!< record is already present */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< 5-byte record header (out_ctr+8) */ + unsigned char *out_iv; /*!< ivlen-byte IV (out_hdr+5) */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ + +#if defined(POLARSSL_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength chosen by us */ +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< flag for record splitting: + -1 disabled, 0 todo, 1 done */ +#endif + + /* + * PKI layer + */ +#if defined(POLARSSL_X509_CRT_PARSE_C) + ssl_key_cert *key_cert; /*!< own certificate(s)/key(s) */ + + x509_crt *ca_chain; /*!< own trusted CA chain */ + x509_crl *ca_crl; /*!< trusted CA CRLs */ + const char *peer_cn; /*!< expected peer CN */ +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + /* + * Support for generating and checking session tickets + */ +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl_ticket_keys *ticket_keys; /*!< keys for ticket encryption */ +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + /* + * User settings + */ + int endpoint; /*!< 0: client, 1: server */ + int authmode; /*!< verification mode */ + int client_auth; /*!< flag for client auth. */ + int verify_result; /*!< verification result */ +#if defined(POLARSSL_SSL_RENEGOTIATION) + int disable_renegotiation; /*!< enable/disable renegotiation */ + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + int allow_legacy_renegotiation; /*!< allow legacy renegotiation */ + const int *ciphersuite_list[4]; /*!< allowed ciphersuites / version */ +#if defined(POLARSSL_SSL_SET_CURVES) + const ecp_group_id *curve_list; /*!< allowed curves */ +#endif +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< negotiate truncated hmac? */ +#endif +#if defined(POLARSSL_SSL_SESSION_TICKETS) + int session_tickets; /*!< use session tickets? */ + int ticket_lifetime; /*!< session ticket lifetime */ +#endif + +#if defined(POLARSSL_DHM_C) + mpi dhm_P; /*!< prime modulus for DHM */ + mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* + * PSK values + */ + unsigned char *psk; + size_t psk_len; + unsigned char *psk_identity; + size_t psk_identity_len; +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + /* + * SNI extension + */ + unsigned char *hostname; + size_t hostname_len; +#endif + +#if defined(POLARSSL_SSL_ALPN) + /* + * ALPN extension + */ + const char **alpn_list; /*!< ordered list of supported protocols */ + const char *alpn_chosen; /*!< negotiated protocol */ +#endif + + /* + * Secure renegotiation + */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(POLARSSL_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif +}; + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + +#define SSL_CHANNEL_OUTBOUND 0 +#define SSL_CHANNEL_INBOUND 1 + +extern int (*ssl_hw_record_init)(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); +extern int (*ssl_hw_record_activate)(ssl_context *ssl, int direction); +extern int (*ssl_hw_record_reset)(ssl_context *ssl); +extern int (*ssl_hw_record_write)(ssl_context *ssl); +extern int (*ssl_hw_record_read)(ssl_context *ssl); +extern int (*ssl_hw_record_finish)(ssl_context *ssl); +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Returns the list of ciphersuites supported by the SSL/TLS module. + * + * \return a statically allocated array of ciphersuites, the last + * entry is 0. + */ +const int *ssl_list_ciphersuites( void ); + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * (An individual SSL context is not thread-safe) + * + * \param ssl SSL context + * + * \return 0 if successful, or POLARSSL_ERR_SSL_MALLOC_FAILED if + * memory allocation failed + */ +int ssl_init( ssl_context *ssl ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or POLASSL_ERR_SSL_MALLOC_FAILED, + POLARSSL_ERR_SSL_HW_ACCEL_FAILED or + * POLARSSL_ERR_SSL_COMPRESSION_FAILED + */ +int ssl_session_reset( ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param ssl SSL context + * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER + * + * \note This function should be called right after ssl_init() since + * some other ssl_set_foo() functions depend on it. + */ +void ssl_set_endpoint( ssl_context *ssl, int endpoint ); + +/** + * \brief Set the certificate verification mode + * + * \param ssl SSL context + * \param authmode can be: + * + * SSL_VERIFY_NONE: peer certificate is not checked (default), + * this is insecure and SHOULD be avoided. + * + * SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * ssl_get_verify_result() can be called after the + * handshake is complete. + * + * SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * + * \note On client, SSL_VERIFY_REQUIRED is the recommended mode. + * With SSL_VERIFY_OPTIONAL, the user needs to call ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void ssl_set_authmode( ssl_context *ssl, int authmode ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the verify callback is called for each + * certificate in the chain. For implementation + * information, please see \c x509parse_verify() + * + * \param ssl SSL context + * \param f_vrfy verification function + * \param p_vrfy verification parameter + */ +void ssl_set_verify( ssl_context *ssl, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param ssl SSL context + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void ssl_set_rng( ssl_context *ssl, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * \param ssl SSL context + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void ssl_set_dbg( ssl_context *ssl, + void (*f_dbg)(void *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO read and write callbacks + * + * \param ssl SSL context + * \param f_recv read callback + * \param p_recv read parameter + * \param f_send write callback + * \param p_send write parameter + */ +void ssl_set_bio( ssl_context *ssl, + int (*f_recv)(void *, unsigned char *, size_t), void *p_recv, + int (*f_send)(void *, const unsigned char *, size_t), void *p_send ); + +#if defined(POLARSSL_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param ssl SSL context + * \param f_get_cache session get callback + * \param p_get_cache session get parameter + * \param f_set_cache session set callback + * \param p_set_cache session set parameter + */ +void ssl_set_session_cache( ssl_context *ssl, + int (*f_get_cache)(void *, ssl_session *), void *p_get_cache, + int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache ); +#endif /* POLARSSL_SSL_SRV_C */ + +#if defined(POLARSSL_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * POLARSSL_ERR_SSL_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa ssl_get_session() + */ +int ssl_set_session( ssl_context *ssl, const ssl_session *session ); +#endif /* POLARSSL_SSL_CLI_C */ + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_context. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param ssl SSL context + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ); + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * \param ssl SSL context + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (SSL_MINOR_VERSION_0, + * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, + * SSL_MINOR_VERSION_3 supported) + */ +void ssl_set_ciphersuites_for_version( ssl_context *ssl, + const int *ciphersuites, + int major, int minor ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Set the data required to verify peer certificate + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + * \param peer_cn expected peer CommonName (or NULL) + */ +void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain, + x509_crl *ca_crl, const char *peer_cn ); + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note This function may be called more than once if you want to + * support multiple certificates (eg, one using RSA and one + * using ECDSA). However, on client, currently only the first + * certificate is used (subsequent calls have no effect). + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or POLARSSL_ERR_SSL_MALLOC_FAILED + */ +int ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert, + pk_context *pk_key ); + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +#if defined(POLARSSL_DEPRECATED_WARNING) +#define DEPRECATED __attribute__((deprecated)) +#else +#define DEPRECATED +#endif +#if defined(POLARSSL_RSA_C) +/** + * \brief Set own certificate chain and private RSA key + * + * Note: own_cert should contain IN order from the bottom + * up your certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \deprecated Please use \c ssl_set_own_cert() instead. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param rsa_key own private RSA key + * + * \return 0 on success, or a specific error code. + */ +int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert, + rsa_context *rsa_key ) DEPRECATED; +#endif /* POLARSSL_RSA_C */ + +/** + * \brief Set own certificate and external RSA private + * key and handling callbacks, such as the PKCS#11 wrappers + * or any other external private key handler. + * (see the respective RSA functions in rsa.h for documentation + * of the callback parameters, with the only change being + * that the rsa_context * is a void * in the callbacks) + * + * Note: own_cert should contain IN order from the bottom + * up your certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \deprecated Please use \c pk_init_ctx_rsa_alt() + * and \c ssl_set_own_cert() instead. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param rsa_key alternate implementation private RSA key + * \param rsa_decrypt alternate implementation of \c rsa_pkcs1_decrypt() + * \param rsa_sign alternate implementation of \c rsa_pkcs1_sign() + * \param rsa_key_len function returning length of RSA key in bytes + * + * \return 0 on success, or a specific error code. + */ +int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert, + void *rsa_key, + rsa_decrypt_func rsa_decrypt, + rsa_sign_func rsa_sign, + rsa_key_len_func rsa_key_len ) DEPRECATED; +#undef DEPRECATED +#endif /* POLARSSL_DEPRECATED_REMOVED */ +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the identity name connected + * to it. + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + * + * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED + */ +int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + +/** + * \brief Set the PSK callback (server-side only) (Optional). + * + * If set, the PSK callback is called for each + * handshake where a PSK ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: (void *parameter, + * ssl_context *ssl, const unsigned char *psk_identity, + * size_t identity_len) + * If a valid PSK identity is found, the callback should use + * ssl_set_psk() on the ssl context to set the correct PSK and + * identity and return 0. + * Any other return value will result in a denied PSK identity. + * + * \param ssl SSL context + * \param f_psk PSK identity function + * \param p_psk PSK identity parameter + */ +void ssl_set_psk_cb( ssl_context *ssl, + int (*f_psk)(void *, ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_DHM_C) +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default: POLARSSL_DHM_RFC5114_MODP_1024_[PG]) + * + * \param ssl SSL context + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \return 0 if successful + */ +int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param ssl SSL context + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ); +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_SSL_SET_CURVES) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves used by peer to the + * listed curves for any use (ECDH(E), certificates). + * + * \param ssl SSL context + * \param curves Ordered list of allowed curves, + * terminated by POLARSSL_ECP_DP_NONE. + */ +void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curves ); +#endif /* POLARSSL_SSL_SET_CURVES */ + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set hostname for ServerName TLS extension + * (client-side only) + * + * + * \param ssl SSL context + * \param hostname the server hostname + * + * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED + */ +int ssl_set_hostname( ssl_context *ssl, const char *hostname ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback should set the + * certificate and key to use with ssl_set_own_cert() (and + * possibly adjust the CA chain as well) and return 0. The + * callback should return -1 to abort the handshake at this + * point. + * + * \param ssl SSL context + * \param f_sni verification function + * \param p_sni verification parameter + */ +void ssl_set_sni( ssl_context *ssl, + int (*f_sni)(void *, ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +#if defined(POLARSSL_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param ssl SSL context + * \param protos NULL-terminated list of supported protocols, + * in decreasing preference order. + * + * \return 0 on success, or POLARSSL_ERR_SSL_BAD_INPUT_DATA. + */ +int ssl_set_alpn_protocols( ssl_context *ssl, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *ssl_get_alpn_protocol( const ssl_context *ssl ); +#endif /* POLARSSL_SSL_ALPN */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: SSL_MAX_MAJOR_VERSION, SSL_MAX_MINOR_VERSION) + * + * Note: This ignores ciphersuites from 'higher' versions. + * Note: Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \param ssl SSL context + * \param major Major version number (only SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (SSL_MINOR_VERSION_0, + * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, + * SSL_MINOR_VERSION_3 supported) + */ +void ssl_set_max_version( ssl_context *ssl, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: SSL_MIN_MAJOR_VERSION, SSL_MIN_MINOR_VERSION) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \param ssl SSL context + * \param major Major version number (only SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (SSL_MINOR_VERSION_0, + * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, + * SSL_MINOR_VERSION_3 supported) + */ +void ssl_set_min_version( ssl_context *ssl, int major, int minor ); + +#if defined(POLARSSL_SSL_FALLBACK_SCSV) && defined(POLARSSL_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: SSL_IS_NOT_FALLBACK). + * + * \note Set to SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \param ssl SSL context + * \param fallback SSL_IS_NOT_FALLBACK or SSL_IS_FALLBACK + */ +void ssl_set_fallback( ssl_context *ssl, char fallback ); +#endif /* POLARSSL_SSL_FALLBACK_SCSV && POLARSSL_SSL_CLI_C */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param ssl SSL context + * \param etm SSL_ETM_ENABLED or SSL_ETM_DISABLED + */ +void ssl_set_encrypt_then_mac( ssl_context *ssl, char etm ); +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param ssl SSL context + * \param ems SSL_EXTENDED_MS_ENABLED or SSL_EXTENDED_MS_DISABLED + */ +void ssl_set_extended_master_secret( ssl_context *ssl, char ems ); +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + +/** + * \brief Disable or enable support for RC4 + * (Default: SSL_ARC4_ENABLED) + * + * \note Though the default is RC4 for compatibility reasons in the + * 1.3 branch, the recommended value is SSL_ARC4_DISABLED. + * + * \note This function will likely be removed in future versions as + * RC4 will then be disabled by default at compile time. + * + * \param ssl SSL context + * \param arc4 SSL_ARC4_ENABLED or SSL_ARC4_DISABLED + */ +void ssl_set_arc4_support( ssl_context *ssl, char arc4 ); + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate + * (Default: SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * + * \param ssl SSL context + * \param mfl_code Code for maximum fragment length (allowed values: + * SSL_MAX_FRAG_LEN_512, SSL_MAX_FRAG_LEN_1024, + * SSL_MAX_FRAG_LEN_2048, SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or POLARSSL_ERR_SSL_BAD_INPUT_DATA + */ +int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ); +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: SSL_TRUNC_HMAC_DISABLED on client, + * SSL_TRUNC_HMAC_ENABLED on server.) + * + * \param ssl SSL context + * \param truncate Enable or disable (SSL_TRUNC_HMAC_ENABLED or + * SSL_TRUNC_HMAC_DISABLED) + * + * \return Always 0. + */ +int ssl_set_truncated_hmac( ssl_context *ssl, int truncate ); +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param ssl SSL context + * \param split SSL_CBC_RECORD_SPLITTING_ENABLED or + * SSL_CBC_RECORD_SPLITTING_DISABLED + */ +void ssl_set_cbc_record_splitting( ssl_context *ssl, char split ); +#endif /* POLARSSL_SSL_CBC_RECORD_SPLITTING */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/** + * \brief Enable / Disable session tickets + * (Default: SSL_SESSION_TICKETS_ENABLED on client, + * SSL_SESSION_TICKETS_DISABLED on server) + * + * \note On server, ssl_set_rng() must be called before this function + * to allow generating the ticket encryption and + * authentication keys. + * + * \param ssl SSL context + * \param use_tickets Enable or disable (SSL_SESSION_TICKETS_ENABLED or + * SSL_SESSION_TICKETS_DISABLED) + * + * \return 0 if successful, + * or a specific error code (server only). + */ +int ssl_set_session_tickets( ssl_context *ssl, int use_tickets ); + +/** + * \brief Set session ticket lifetime (server only) + * (Default: SSL_DEFAULT_TICKET_LIFETIME (86400 secs / 1 day)) + * + * \param ssl SSL context + * \param lifetime session ticket lifetime + */ +void ssl_set_session_ticket_lifetime( ssl_context *ssl, int lifetime ); +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: SSL_RENEGOTIATION_DISABLED) + * + * Note: A server with support enabled is more vulnerable for a + * resource DoS by a malicious client. You should enable this on + * a client to enable server-initiated renegotiation. + * + * \param ssl SSL context + * \param renegotiation Enable or disable (SSL_RENEGOTIATION_ENABLED or + * SSL_RENEGOTIATION_DISABLED) + */ +void ssl_set_renegotiation( ssl_context *ssl, int renegotiation ); +#endif /* POLARSSL_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: SSL_LEGACY_NO_RENEGOTIATION) + * + * SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param ssl SSL context + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * SSL_LEGACY_BREAK_HANDSHAKE) + */ +void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) +/** + * \brief Enforce requested renegotiation. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \warning On client, the grace period can only happen during + * ssl_read(), as opposed to ssl_write() and ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during ssl_read(). + * + * \param ssl SSL context + * \param max_records Use SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^64 - 256.) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or ingoing) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * \param ssl SSL context + * \param period The threshold value: a big-endian 64-bit number. + * Set to 2^64 - 1 to disable periodic renegotiation + */ +void ssl_set_renegotiation_period( ssl_context *ssl, + const unsigned char period[8] ); +#endif /* POLARSSL_SSL_RENEGOTIATION */ + +/** + * \brief Return the number of data bytes available to read + * + * \param ssl SSL context + * + * \return how many bytes are available in the read buffer + */ +size_t ssl_get_bytes_avail( const ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl SSL context + * + * \return 0 if successful, + * -1 if result is not available (eg because the handshake was + * aborted too early), or + * a combination of BADCERT_xxx and BADCRL_xxx flags, see + * x509.h + */ +int ssl_get_verify_result( const ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *ssl_get_ciphersuite( const ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *ssl_get_version( const ssl_context *ssl ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection + * + * Note: Can be NULL in case no certificate was sent during + * the handshake. Different calls for the same connection can + * return the same or different pointers for the same + * certificate and even a different certificate altogether. + * The peer cert CAN change in a single connection if + * renegotiation is performed. + * + * \param ssl SSL context + * + * \return the current peer certificate + */ +const x509_crt *ssl_get_peer_cert( const ssl_context *ssl ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_SSL_CLI_C) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * \warning Currently, peer certificate is lost in the operation. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * POLARSSL_ERR_SSL_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa ssl_set_session() + */ +int ssl_get_session( const ssl_context *ssl, ssl_session *session ); +#endif /* POLARSSL_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ, + * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code. + */ +int ssl_handshake( ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * Note: the state of the context (ssl->state) will be at + * the following state after execution of this function. + * Do not call this function if state is SSL_HANDSHAKE_OVER. + * + * \param ssl SSL context + * + * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ, + * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code. + */ +int ssl_handshake_step( ssl_context *ssl ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to ssl_read() if honored by client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any ssl_handshake() return value. + */ +int ssl_renegotiate( ssl_context *ssl ); +#endif /* POLARSSL_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return This function returns the number of bytes read, 0 for EOF, + * or a negative error code. + */ +int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Write exactly 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return This function returns the number of bytes written, + * or a negative error code. + * + * \note When this function returns POLARSSL_ERR_NET_WANT_WRITE, + * it must be called later with the *same* arguments, + * until it returns a positive value. + * + * \note This function may write less than the number of bytes + * requested if len is greater than the maximum record length. + * For arbitrary-sized messages, it should be called in a loop. + */ +int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (SSL_ALERT_LEVEL_WARNING or SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + */ +int ssl_send_alert_message( ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + */ +int ssl_close_notify( ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void ssl_free( ssl_context *ssl ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void ssl_session_init( ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \param session SSL session + */ +void ssl_session_free( ssl_session *session ); + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void ssl_transform_free( ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param handshake SSL handshake context + */ +void ssl_handshake_free( ssl_handshake_params *handshake ); + +/* + * Internal functions (do not call directly) + */ +int ssl_handshake_client_step( ssl_context *ssl ); +int ssl_handshake_server_step( ssl_context *ssl ); +void ssl_handshake_wrapup( ssl_context *ssl ); + +int ssl_send_fatal_handshake_failure( ssl_context *ssl ); + +int ssl_derive_keys( ssl_context *ssl ); + +int ssl_read_record( ssl_context *ssl ); +/** + * \return 0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or + * another negative error code. + */ +int ssl_fetch_input( ssl_context *ssl, size_t nb_want ); + +int ssl_write_record( ssl_context *ssl ); +int ssl_flush_output( ssl_context *ssl ); + +int ssl_parse_certificate( ssl_context *ssl ); +int ssl_write_certificate( ssl_context *ssl ); + +int ssl_parse_change_cipher_spec( ssl_context *ssl ); +int ssl_write_change_cipher_spec( ssl_context *ssl ); + +int ssl_parse_finished( ssl_context *ssl ); +int ssl_write_finished( ssl_context *ssl ); + +void ssl_optimize_checksum( ssl_context *ssl, + const ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ); +#endif + +#if defined(POLARSSL_PK_C) +unsigned char ssl_sig_from_pk( pk_context *pk ); +pk_type_t ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +md_type_t ssl_md_alg_from_hash( unsigned char hash ); + +#if defined(POLARSSL_SSL_SET_CURVES) +int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +static inline pk_context *ssl_own_key( ssl_context *ssl ) +{ + return( ssl->handshake->key_cert == NULL ? NULL + : ssl->handshake->key_cert->key ); +} + +static inline x509_crt *ssl_own_cert( ssl_context *ssl ) +{ + return( ssl->handshake->key_cert == NULL ? NULL + : ssl->handshake->key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int ssl_check_cert_usage( const x509_crt *cert, + const ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + int *flags ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/* constant-time buffer comparison */ +static inline int safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ssl_cache.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ssl_cache.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,145 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SSL_CACHE_H +#define POLARSSL_SSL_CACHE_H + +#include "ssl.h" + +#if defined(POLARSSL_THREADING_C) +#include "threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(SSL_CACHE_DEFAULT_TIMEOUT) +#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _ssl_cache_context ssl_cache_context; +typedef struct _ssl_cache_entry ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct _ssl_cache_entry +{ +#if defined(POLARSSL_HAVE_TIME) + time_t timestamp; /*!< entry timestamp */ +#endif + ssl_session session; /*!< entry session */ +#if defined(POLARSSL_X509_CRT_PARSE_C) + x509_buf peer_cert; /*!< entry peer_cert */ +#endif + ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct _ssl_cache_context +{ + ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(POLARSSL_THREADING_C) + threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void ssl_cache_init( ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int ssl_cache_get( void *data, ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int ssl_cache_set( void *data, const ssl_session *session ); + +#if defined(POLARSSL_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout ); +#endif /* POLARSSL_HAVE_TIME */ + +/** + * \brief Set the cache timeout + * (Default: SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void ssl_cache_set_max_entries( ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void ssl_cache_free( ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/ssl_ciphersuites.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/ssl_ciphersuites.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,304 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_CIPHERSUITES_H + +#include "pk.h" +#include "cipher.h" +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define TLS_RSA_WITH_RC4_128_MD5 0x04 +#define TLS_RSA_WITH_RC4_128_SHA 0x05 +#define TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define TLS_PSK_WITH_RC4_128_SHA 0x8A +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +/* Reminder: update _ssl_premaster_secret when adding a new key exchange. + * Reminder: update POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED below. + */ +typedef enum { + POLARSSL_KEY_EXCHANGE_NONE = 0, + POLARSSL_KEY_EXCHANGE_RSA, + POLARSSL_KEY_EXCHANGE_DHE_RSA, + POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + POLARSSL_KEY_EXCHANGE_PSK, + POLARSSL_KEY_EXCHANGE_DHE_PSK, + POLARSSL_KEY_EXCHANGE_RSA_PSK, + POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + POLARSSL_KEY_EXCHANGE_ECDH_RSA, + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, +} key_exchange_type_t; + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED +#endif + +typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t; + +#define POLARSSL_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define POLARSSL_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct _ssl_ciphersuite_t +{ + int id; + const char * name; + + cipher_type_t cipher; + md_type_t mac; + key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *ssl_list_ciphersuites( void ); + +const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(POLARSSL_PK_C) +pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info ); +#endif + +int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info ); +int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/threading.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/threading.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,84 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_THREADING_H +#define POLARSSL_THREADING_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define POLARSSL_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(POLARSSL_THREADING_PTHREAD) +#include <pthread.h> +typedef pthread_mutex_t threading_mutex_t; +#endif + +#if defined(POLARSSL_THREADING_ALT) +/* You should define the threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + * + * \return 0 if successful + */ +int threading_set_alt( int (*mutex_init)( threading_mutex_t * ), + int (*mutex_free)( threading_mutex_t * ), + int (*mutex_lock)( threading_mutex_t * ), + int (*mutex_unlock)( threading_mutex_t * ) ); +#endif /* POLARSSL_THREADING_ALT_C */ + +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern int (*polarssl_mutex_init)( threading_mutex_t *mutex ); +extern int (*polarssl_mutex_free)( threading_mutex_t *mutex ); +extern int (*polarssl_mutex_lock)( threading_mutex_t *mutex ); +extern int (*polarssl_mutex_unlock)( threading_mutex_t *mutex ); + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/timing.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/timing.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,100 @@ +/** + * \file timing.h + * + * \brief Portable interface to the CPU cycle counter + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_TIMING_H +#define POLARSSL_TIMING_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if !defined(POLARSSL_TIMING_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief timer structure + */ +struct hr_time +{ + unsigned char opaque[32]; +}; + +extern volatile int alarmed; + +/** + * \brief Return the CPU cycle counter value + */ +unsigned long hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset if set to 1, the timer is restarted + */ +unsigned long get_timer( struct hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "alarmed" flag is set + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void set_alarm( int seconds ); + +/** + * \brief Sleep for a certain amount of time + * + * \param milliseconds delay in milliseconds + */ +void m_sleep( int milliseconds ); + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_TIMING_ALT */ +#include "timing_alt.h" +#endif /* POLARSSL_TIMING_ALT */ + +#endif /* timing.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/version.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/version.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,112 @@ +/** + * \file version.h + * + * \brief Run-time version information + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This set of compile-time defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef POLARSSL_VERSION_H +#define POLARSSL_VERSION_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define POLARSSL_VERSION_MAJOR 1 +#define POLARSSL_VERSION_MINOR 3 +#define POLARSSL_VERSION_PATCH 11 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define POLARSSL_VERSION_NUMBER 0x01030B00 +#define POLARSSL_VERSION_STRING "1.3.11" +#define POLARSSL_VERSION_STRING_FULL "mbed TLS 1.3.11" + +#if defined(POLARSSL_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * Note: only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "POLARSSL_AES_C") + * + * \return 0 if the feature is present, -1 if the feature is not + * present and -2 if support for feature checking as a whole + * was not compiled in. + */ +int version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_VERSION_C */ + +#endif /* version.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/x509.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/x509.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,343 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_H +#define POLARSSL_X509_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#if defined(POLARSSL_RSA_C) +#include "rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(POLARSSL_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define POLARSSL_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define POLARSSL_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define POLARSSL_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define POLARSSL_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define POLARSSL_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define POLARSSL_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define POLARSSL_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::x509_crt sig_oid) */ +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define POLARSSL_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define POLARSSL_ERR_X509_MALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define POLARSSL_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + */ +#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define KU_CRL_SIGN (0x02) /* bit 6 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define EXT_KEY_USAGE (1 << 2) /* Parsed but not used */ +#define EXT_CERTIFICATE_POLICIES (1 << 3) +#define EXT_POLICY_MAPPINGS (1 << 4) +#define EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define EXT_ISSUER_ALT_NAME (1 << 6) +#define EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define EXT_NAME_CONSTRAINTS (1 << 9) +#define EXT_POLICY_CONSTRAINTS (1 << 10) +#define EXT_EXTENDED_KEY_USAGE (1 << 11) /* Parsed but not used */ +#define EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define EXT_FRESHEST_CRL (1 << 14) + +#define EXT_NS_CERT_TYPE (1 << 16) /* Parsed (and then ?) */ + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define X509_FORMAT_DER 1 +#define X509_FORMAT_PEM 2 + +#define X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef asn1_buf x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef asn1_bitstring x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.). + */ +typedef asn1_named_data x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef asn1_sequence x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct _x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_dn_gets( char *buf, size_t size, const x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_serial_gets( char *buf, size_t size, const x509_buf *serial ); + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +#if defined(POLARSSL_DEPRECATED_WARNING) +#define DEPRECATED __attribute__((deprecated)) +#else +#define DEPRECATED +#endif +/** + * \brief Give an known OID, return its descriptive string. + * + * \deprecated Use oid_get_extended_key_usage() instead. + * + * \warning Only works for extended_key_usage OIDs! + * + * \param oid buffer containing the oid + * + * \return Return a string if the OID is known, + * or NULL otherwise. + */ +const char *x509_oid_get_description( x509_buf *oid ) DEPRECATED; + +/** + * \brief Give an OID, return a string version of its OID number. + * + * \deprecated Use oid_get_numeric_string() instead. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param oid Buffer containing the OID + * + * \return Length of the string written (excluding final NULL) or + * POLARSSL_ERR_OID_BUF_TO_SMALL in case of error + */ +int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid ) DEPRECATED; +#undef DEPRECATED +#endif /* POLARSSL_DEPRECATED_REMOVED */ + +/** + * \brief Check a given x509_time against the system time and check + * if it is not expired. + * + * \param time x509_time to check + * + * \return 0 if the x509_time is still valid, + * 1 otherwise. + */ +int x509_time_expired( const x509_time *time ); + +/** + * \brief Check a given x509_time against the system time and check + * if it is not from the future. + * + * \param time x509_time to check + * + * \return 0 if the x509_time is already valid, + * 1 otherwise. + */ +int x509_time_future( const x509_time *time ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int x509_self_test( int verbose ); + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int x509_get_name( unsigned char **p, const unsigned char *end, + x509_name *cur ); +int x509_get_alg_null( unsigned char **p, const unsigned char *end, + x509_buf *alg ); +int x509_get_alg( unsigned char **p, const unsigned char *end, + x509_buf *alg, x509_buf *params ); +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) +int x509_get_rsassa_pss_params( const x509_buf *params, + md_type_t *md_alg, md_type_t *mgf_md, + int *salt_len ); +#endif +int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig ); +int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params, + md_type_t *md_alg, pk_type_t *pk_alg, + void **sig_opts ); +int x509_get_time( unsigned char **p, const unsigned char *end, + x509_time *time ); +int x509_get_serial( unsigned char **p, const unsigned char *end, + x509_buf *serial ); +int x509_get_ext( unsigned char **p, const unsigned char *end, + x509_buf *ext, int tag ); +int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid, + pk_type_t pk_alg, md_type_t md_alg, + const void *sig_opts ); +int x509_key_size_helper( char *buf, size_t size, const char *name ); +int x509_string_to_names( asn1_named_data **head, const char *name ); +int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int x509_write_extensions( unsigned char **p, unsigned char *start, + asn1_named_data *first ); +int x509_write_names( unsigned char **p, unsigned char *start, + asn1_named_data *first ); +int x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/x509_crl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/x509_crl.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,173 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_CRL_H +#define POLARSSL_X509_CRL_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct _x509_crl_entry +{ + x509_buf raw; + + x509_buf serial; + + x509_time revocation_date; + + x509_buf entry_ext; + + struct _x509_crl_entry *next; +} +x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct _x509_crl +{ + x509_buf raw; /**< The raw certificate data (DER). */ + x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + x509_buf sig_oid1; + + x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + x509_name issuer; /**< The parsed issuer data (named information object). */ + + x509_time this_update; + x509_time next_update; + + x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + x509_buf crl_ext; + + x509_buf sig_oid2; + x509_buf sig; + md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ + pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct _x509_crl *next; +} +x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_crl_parse_der( x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_crl_parse_file( x509_crl *chain, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_crl_info( char *buf, size_t size, const char *prefix, + const x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void x509_crl_init( x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void x509_crl_free( x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* x509_crl.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/x509_crt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/x509_crt.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,569 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_CRT_H +#define POLARSSL_X509_CRT_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "x509.h" +#include "x509_crl.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct _x509_crt +{ + x509_buf raw; /**< The raw certificate data (DER). */ + x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + x509_buf sig_oid1; /**< Signature algorithm, e.g. sha1RSA */ + + x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + x509_name issuer; /**< The parsed issuer data (named information object). */ + x509_name subject; /**< The parsed subject data (named information object). */ + + x509_time valid_from; /**< Start time of certificate validity. */ + x509_time valid_to; /**< End time of certificate validity. */ + + pk_context pk; /**< Container for the public key context. */ + + x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned char key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + x509_buf sig_oid2; /**< Signature algorithm. Must match sig_oid1. */ + x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ + pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct _x509_crt *next; /**< Next certificate in the CA-chain. */ +} +x509_crt; + +#define X509_CRT_VERSION_1 0 +#define X509_CRT_VERSION_2 1 +#define X509_CRT_VERSION_3 2 + +#define X509_RFC5280_MAX_SERIAL_LEN 32 +#define X509_RFC5280_UTC_TIME_LEN 15 + +/** + * Container for writing a certificate (CRT) + */ +typedef struct _x509write_cert +{ + int version; + mpi serial; + pk_context *subject_key; + pk_context *issuer_key; + asn1_named_data *subject; + asn1_named_data *issuer; + md_type_t md_alg; + char not_before[X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[X509_RFC5280_UTC_TIME_LEN + 1]; + asn1_named_data *extensions; +} +x509write_cert; + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data + * \param buflen size of the buffer + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int x509_crt_parse_file( x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \warning This function is NOT thread-safe unless + * POLARSSL_THREADING_PTHREADS is defined. If you're using an + * alternative threading implementation, you should either use + * this function only in the main thread, or mutex it. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int x509_crt_parse_path( x509_crt *chain, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_crt_info( char *buf, size_t size, const char *prefix, + const x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by x509_crt_verify() + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_crt_verify_info( char *buf, size_t size, const char *prefix, + int flags ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything but a fatal error. + * + * \note In case verification failed, the results can be displayed + * using \c x509_crt_verify_info() + * + * \param crt a certificate to be verified + * \param trust_ca the trusted CA chain + * \param ca_crl the CRL chain for trusted CA's + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED, + * in which case *flags will have one or more BADCERT_XXX or + * BADCRL_XXX flags set, + * or another error in case of a fatal error encountered + * during the verification process. + */ +int x509_crt_verify( x509_crt *crt, + x509_crt *trust_ca, + x509_crl *ca_crl, + const char *cn, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ); + +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg KU_KEY_ENCIPHERMENT before using the + * certificate to perform an RSA key exchange). + * + * \return 0 is these uses of the certificate are allowed, + * POLARSSL_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not contain all the bits set in the + * usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c x509_crt_verify(). + */ +int x509_crt_check_key_usage( const x509_crt *crt, int usage ); +#endif /* POLARSSL_X509_CHECK_KEY_USAGE) */ + +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extentedJeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg OID_SERVER_AUTH or OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by OID_SIZE()). + * + * \return 0 is this use of the certificate is allowed, + * POLARSSL_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int x509_crt_check_extended_key_usage( const x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) */ + +#if defined(POLARSSL_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl ); +#endif /* POLARSSL_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void x509_crt_init( x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void x509_crt_free( x509_crt *crt ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(POLARSSL_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void x509write_crt_init( x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (X509_CRT_VERSION_1, X509_CRT_VERSION_2 or + * X509_CRT_VERSION_3) + */ +void x509write_crt_set_version( x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_issuer_name( x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_subject_name( x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. POLARSSL_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_extension( x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_basic_constraints( x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(POLARSSL_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ); +#endif /* POLARSSL_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_ns_cert_type( x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void x509write_crt_free( x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* x509_crt.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/x509_csr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/x509_csr.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,293 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_CSR_H +#define POLARSSL_X509_CSR_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct _x509_csr +{ + x509_buf raw; /**< The raw CSR data (DER). */ + x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + x509_buf subject_raw; /**< The raw subject data (DER). */ + x509_name subject; /**< The parsed subject data (named information object). */ + + pk_context pk; /**< Container for the public key context. */ + + x509_buf sig_oid; + x509_buf sig; + md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ + pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */ +} +x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct _x509write_csr +{ + pk_context *key; + asn1_named_data *subject; + md_type_t md_alg; + asn1_named_data *extensions; +} +x509write_csr; + +#if defined(POLARSSL_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int x509_csr_parse_der( x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_csr_parse_file( x509_csr *csr, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (exluding the terminating + * null byte), or a negative value in case of an error. + */ +int x509_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void x509_csr_init( x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void x509_csr_free( x509_csr *csr ); +#endif /* POLARSSL_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(POLARSSL_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void x509write_csr_init( x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int x509write_csr_set_subject_name( x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void x509write_csr_set_key( x509write_csr *ctx, pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. POLARSSL_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_ns_cert_type( x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_extension( x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void x509write_csr_free( x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for couermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* x509_csr.h */ +
diff -r 000000000000 -r 137634ff4186 include/polarssl/xtea.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/polarssl/xtea.h Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,147 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + * + * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_XTEA_H +#define POLARSSL_XTEA_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include <stddef.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#define XTEA_ENCRYPT 1 +#define XTEA_DECRYPT 0 + +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ + +#if !defined(POLARSSL_XTEA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief XTEA context structure + */ +typedef struct +{ + uint32_t k[4]; /*!< key */ +} +xtea_context; + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void xtea_init( xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void xtea_free( xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void xtea_setup( xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode XTEA_ENCRYPT or XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int xtea_crypt_ecb( xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode XTEA_ENCRYPT or XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int xtea_crypt_cbc( xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* POLARSSL_XTEA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int xtea_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ +
diff -r 000000000000 -r 137634ff4186 polarssl/aes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/aes.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1453 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_AES_C) + +#include <string.h> + +#include "polarssl/aes.h" +#if defined(POLARSSL_PADLOCK_C) +#include "polarssl/padlock.h" +#endif +#if defined(POLARSSL_AESNI_C) +#include "polarssl/aesni.h" +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +#if !defined(POLARSSL_AES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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(POLARSSL_PADLOCK_C) && \ + ( defined(POLARSSL_HAVE_X86) || defined(PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(POLARSSL_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 /* POLARSSL_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 /* POLARSSL_AES_ROM_TABLES */ + +void aes_init( aes_context *ctx ) +{ + memset( ctx, 0, sizeof( aes_context ) ); +} + +void aes_free( aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( aes_context ) ); +} + +/* + * AES key schedule (encryption) + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(POLARSSL_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = padlock_supports( PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_AESNI_AES ) ) + return( aesni_setkey_enc( (unsigned char *) ctx->rk, key, keysize ) ); +#endif + + for( i = 0; i < ( keysize >> 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 ); +} + +/* + * AES key schedule (decryption) + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + int i, j, ret; + aes_context cty; + uint32_t *RK; + uint32_t *SK; + + aes_init( &cty ); + +#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = padlock_supports( PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keysize */ + if( ( ret = aes_setkey_enc( &cty, key, keysize ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_AESNI_AES ) ) + { + 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: + aes_free( &cty ); + + return( ret ); +} + +#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/decryption + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_AESNI_AES ) ) + return( aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if( aes_padlock_ace ) + { + if( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + 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++; + + if( mode == AES_DECRYPT ) + { + 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 ); + } + else /* AES_ENCRYPT */ + { + 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 ); + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int aes_crypt_cbc( 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( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if( aes_padlock_ace ) + { + if( 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 == AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + 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] ); + + aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int aes_crypt_cfb128( 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 == AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + aes_crypt_ecb( ctx, 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 ) + aes_crypt_ecb( ctx, 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 aes_crypt_cfb8( 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 ); + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + if( mode == AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int aes_crypt_ctr( 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 ) { + aes_crypt_ecb( ctx, 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 /* POLARSSL_CIPHER_MODE_CTR */ + +#endif /* !POLARSSL_AES_ALT */ + +#if defined(POLARSSL_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(POLARSSL_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 /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_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 /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_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 /* POLARSSL_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int 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(POLARSSL_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB) + size_t offset; +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + int len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + aes_context ctx; + + memset( key, 0, 32 ); + aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[16]; + + 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 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); + + offset = 0; + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + if( v == AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-CTR-128 (%s): ", + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + aes_setkey_enc( &ctx, key, 128 ); + + if( v == AES_DECRYPT ) + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_ct[u], len ); + + 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 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_pt[u], len ); + + 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 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + aes_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_AES_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/aesni.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/aesni.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,462 @@ +/* + * AES-NI support functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * [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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_AESNI_C) + +#include "polarssl/aesni.h" + +#include <string.h> + +#if defined(POLARSSL_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int aesni_supports( 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 aesni_crypt_ecb( 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 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 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 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 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( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* POLARSSL_HAVE_X86_64 */ + +#endif /* POLARSSL_AESNI_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/arc4.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/arc4.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,207 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ARC4_C) + +#include "polarssl/arc4.h" + +#include <string.h> + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +#if !defined(POLARSSL_ARC4_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void arc4_init( arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( arc4_context ) ); +} + +void arc4_free( arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void arc4_setup( 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 arc4_crypt( 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 /* !POLARSSL_ARC4_ALT */ + +#if defined(POLARSSL_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 arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + arc4_context ctx; + + arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + arc4_setup( &ctx, arc4_test_key[i], 8 ); + arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + arc4_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ARC4_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/asn1parse.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/asn1parse.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,396 @@ +/* + * Generic ASN.1 parsing + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ASN1_PARSE_C) + +#include "polarssl/asn1.h" + +#include <string.h> + +#if defined(POLARSSL_BIGNUM_C) +#include "polarssl/bignum.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * ASN.1 DER decoding routines + */ +int asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( POLARSSL_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( POLARSSL_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( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( asn1_get_len( p, end, len ) ); +} + +int asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(POLARSSL_BIGNUM_C) +int asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* POLARSSL_BIGNUM_C */ + +int asn1_get_bitstring( unsigned char **p, const unsigned char *end, + asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( POLARSSL_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( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret; + + if( ( ret = asn1_get_tag( p, end, len, ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( (*len)-- < 2 || *(*p)++ != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF <tag>" + */ +int asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = 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 = polarssl_malloc( sizeof( asn1_sequence ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_ASN1_MALLOC_FAILED ); + + memset( cur->next, 0, sizeof( asn1_sequence ) ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int asn1_get_alg( unsigned char **p, + const unsigned char *end, + asn1_buf *alg, asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + polarssl_zeroize( params, sizeof(asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + asn1_buf *alg ) +{ + int ret; + asn1_buf params; + + memset( ¶ms, 0, sizeof(asn1_buf) ); + + if( ( ret = asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void asn1_free_named_data( asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + polarssl_free( cur->oid.p ); + polarssl_free( cur->val.p ); + + polarssl_zeroize( cur, sizeof( asn1_named_data ) ); +} + +void asn1_free_named_data_list( asn1_named_data **head ) +{ + asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + asn1_free_named_data( cur ); + polarssl_free( cur ); + } +} + +asn1_named_data *asn1_find_named_data( 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 /* POLARSSL_ASN1_PARSE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/asn1write.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/asn1write.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,366 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ASN1_WRITE_C) + +#include "polarssl/asn1write.h" + +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( *p - start < 3 ) + return( POLARSSL_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 asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p - start < (int) size ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(POLARSSL_BIGNUM_C) +int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ) +{ + int ret; + size_t len = 0; + + // Write the MPI + // + len = mpi_size( X ); + + if( *p - start < (int) len ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MPI_CHK( 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( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* POLARSSL_BIGNUM_C */ + +int asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret; + size_t len = 0; + + // Write NULL + // + ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) ); + + return( (int) len ); +} + +int asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) ); + + return( (int) len ); +} + +int 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 ) + ASN1_CHK_ADD( len, asn1_write_null( p, start ) ); + else + len += par_len; + + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 1 : 0; + len++; + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +int 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( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len += 1; + *--(*p) = val; + + if( val > 0 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); + + return( (int) len ); +} + +int asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) ); + + return( (int) len ); +} + +int asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) ); + + return( (int) len ); +} + +int 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 < (int) size + 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size + 1; + (*p) -= size; + memcpy( *p, buf, size ); + + // Write unused bits + // + *--(*p) = (unsigned char) (size * 8 - bits); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, buf, size ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + +asn1_named_data *asn1_store_named_data( asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + if( ( cur = polarssl_malloc( sizeof(asn1_named_data) ) ) == NULL ) + return( NULL ); + + memset( cur, 0, sizeof(asn1_named_data) ); + + cur->oid.len = oid_len; + cur->oid.p = polarssl_malloc( oid_len ); + if( cur->oid.p == NULL ) + { + polarssl_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( NULL ); + } + + cur->next = *head; + *head = cur; + } + else if( cur->val.len < val_len ) + { + // Enlarge existing value buffer if needed + // + polarssl_free( cur->val.p ); + cur->val.p = NULL; + + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( NULL ); + } + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* POLARSSL_ASN1_WRITE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/base64.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/base64.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,292 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_BASE64_C) + +#include "polarssl/base64.h" + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#include <string.h> +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_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 +}; + +/* + * Encode a buffer into base64 format + */ +int base64_encode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *dlen = 0; + return( 0 ); + } + + n = ( slen << 3 ) / 6; + + switch( ( slen << 3 ) - ( n * 6 ) ) + { + case 2: n += 3; break; + case 4: n += 2; break; + default: break; + } + + if( *dlen < n + 1 ) + { + *dlen = n + 1; + return( POLARSSL_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++ = '='; + } + + *dlen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int base64_decode( unsigned char *dst, size_t *dlen, + 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( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' && ++j > 2 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + return( 0 ); + + n = ( ( n * 6 ) + 7 ) >> 3; + n -= j; + + if( dst == NULL || *dlen < n ) + { + *dlen = n; + return( POLARSSL_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 ); + } + } + + *dlen = p - dst; + + return( 0 ); +} + +#if defined(POLARSSL_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 base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + polarssl_printf( " Base64 encoding test: " ); + + len = sizeof( buffer ); + src = base64_test_dec; + + if( base64_encode( buffer, &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n Base64 decoding test: " ); + + len = sizeof( buffer ); + src = base64_test_enc; + + if( base64_decode( buffer, &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_BASE64_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/bignum.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/bignum.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,2354 @@ +/* + * Multi-precision integer library + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This MPI implementation is based on: + * + * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf + * http://www.stillhq.com/extracted/gnupg-api/mpi/ + * http://math.libtomcrypt.com/files/tommath.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_BIGNUM_C) + +#include "polarssl/bignum.h" +#include "polarssl/bn_mul.h" + +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#include <stdlib.h> +#define polarssl_printf printf +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define ciL (sizeof(t_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +/* + * Convert between bits/chars and number of limbs + */ +#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) +#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) + +/* + * Initialize one MPI + */ +void mpi_init( mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mpi_free( mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + polarssl_zeroize( X->p, X->n * ciL ); + polarssl_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mpi_grow( mpi *X, size_t nblimbs ) +{ + t_uint *p; + + if( nblimbs > POLARSSL_MPI_MAX_LIMBS ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = polarssl_malloc( nblimbs * ciL ) ) == NULL ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + memset( p, 0, nblimbs * ciL ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + polarssl_zeroize( X->p, X->n * ciL ); + polarssl_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 mpi_shrink( mpi *X, size_t nblimbs ) +{ + t_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( 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 = polarssl_malloc( i * ciL ) ) == NULL ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + memset( p, 0, i * ciL ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + polarssl_zeroize( X->p, X->n * ciL ); + polarssl_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mpi_copy( mpi *X, const mpi *Y ) +{ + int ret; + size_t i; + + if( X == Y ) + return( 0 ); + + if( Y->p == NULL ) + { + mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MPI_CHK( 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 mpi_swap( mpi *X, mpi *Y ) +{ + mpi T; + + memcpy( &T, X, sizeof( mpi ) ); + memcpy( X, Y, sizeof( mpi ) ); + memcpy( Y, &T, sizeof( 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 mpi_safe_cond_assign( mpi *X, const 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; + + MPI_CHK( 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 mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + t_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; + + MPI_CHK( mpi_grow( X, Y->n ) ); + MPI_CHK( 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 mpi_lset( mpi *X, t_sint z ) +{ + int ret; + + MPI_CHK( 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 mpi_get_bit( const 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 mpi_set_bit( 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( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MPI_CHK( mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (t_uint) 0x01 << idx ); + X->p[off] |= (t_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of least significant bits + */ +size_t mpi_lsb( const 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 ); +} + +/* + * Return the number of most significant bits + */ +size_t mpi_msb( const 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; + + for( j = biL; j > 0; j-- ) + if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 ) + break; + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mpi_size( const mpi *X ) +{ + return( ( mpi_msb( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( t_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 >= (t_uint) radix ) + return( POLARSSL_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mpi_read_string( mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + t_uint d; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + n = BITS_TO_LIMBS( slen << 2 ); + + MPI_CHK( mpi_grow( X, n ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MPI_CHK( mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MPI_CHK( mpi_add_int( X, &T, d ) ); + } + else + { + MPI_CHK( mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mpi *X, int radix, char **p ) +{ + int ret; + t_uint r; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + MPI_CHK( mpi_mod_int( &r, X, radix ) ); + MPI_CHK( mpi_div_int( X, NULL, X, radix ) ); + + if( mpi_cmp_int( X, 0 ) != 0 ) + 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 mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ) +{ + int ret = 0; + size_t n; + char *p; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + n = mpi_msb( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + n += 3; + + if( *slen < n ) + { + *slen = n; + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = s; + 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 + { + MPI_CHK( mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *slen = p - s; + +cleanup: + + mpi_free( &T ); + + return( ret ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Read X from an opened file + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ) +{ + t_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ POLARSSL_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( POLARSSL_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( mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mpi_write_file( const char *p, const 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[ POLARSSL_MPI_RW_BUFFER_SIZE ]; + + n = sizeof( s ); + memset( s, 0, n ); + n -= 2; + + MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &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( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + } + else + polarssl_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mpi_read_binary( 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; + + MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = buflen, j = 0; i > n; i--, j++ ) + X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mpi_size( X ); + + if( buflen < n ) + return( POLARSSL_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 mpi_shift_l( mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + t_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mpi_msb( X ) + count; + + if( X->n * biL < i ) + MPI_CHK( 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 mpi_shift_r( mpi *X, size_t count ) +{ + size_t i, v0, v1; + t_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return 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 mpi_cmp_abs( const mpi *X, const 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 mpi_cmp_mpi( const mpi *X, const 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 mpi_cmp_int( const mpi *X, t_sint z ) +{ + mpi Y; + t_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + t_uint *o, *p, c; + + if( X == B ) + { + const mpi *T = A; A = X; B = T; + } + + if( X != A ) + MPI_CHK( 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; + + MPI_CHK( 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 ) + { + MPI_CHK( mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mpi subtraction + */ +static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d ) +{ + size_t i; + t_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 mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ) +{ + mpi TB; + int ret; + size_t n; + + if( mpi_cmp_abs( A, B ) < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + mpi_init( &TB ); + + if( X == B ) + { + MPI_CHK( mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MPI_CHK( 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: + + mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s < 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s > 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for 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, t_uint *s, t_uint *d, t_uint b ) +{ + t_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 mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + mpi TA, TB; + + mpi_init( &TA ); mpi_init( &TB ); + + if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MPI_CHK( 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; + + MPI_CHK( mpi_grow( X, i + j ) ); + MPI_CHK( 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: + + mpi_free( &TB ); mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Division by mpi: A = Q * B + R (HAC 14.20) + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, n, t, k; + mpi X, Y, Z, T1, T2; + + if( mpi_cmp_int( B, 0 ) == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + mpi_init( &T1 ); mpi_init( &T2 ); + + if( mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); + if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); + return( 0 ); + } + + MPI_CHK( mpi_copy( &X, A ) ); + MPI_CHK( mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); + MPI_CHK( mpi_lset( &Z, 0 ) ); + MPI_CHK( mpi_grow( &T1, 2 ) ); + MPI_CHK( mpi_grow( &T2, 3 ) ); + + k = mpi_msb( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MPI_CHK( mpi_shift_l( &X, k ) ); + MPI_CHK( mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) ); + } + MPI_CHK( 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 + { +#if defined(POLARSSL_HAVE_UDBL) + t_udbl r; + + r = (t_udbl) X.p[i] << biL; + r |= (t_udbl) X.p[i - 1]; + r /= Y.p[t]; + if( r > ( (t_udbl) 1 << biL ) - 1 ) + r = ( (t_udbl) 1 << biL ) - 1; + + Z.p[i - t - 1] = (t_uint) r; +#else + /* + * __udiv_qrnnd_c, from gmp/longlong.h + */ + t_uint q0, q1, r0, r1; + t_uint d0, d1, d, m; + + d = Y.p[t]; + d0 = ( d << biH ) >> biH; + d1 = ( d >> biH ); + + q1 = X.p[i] / d1; + r1 = X.p[i] - d1 * q1; + r1 <<= biH; + r1 |= ( X.p[i - 1] >> biH ); + + m = q1 * d0; + if( r1 < m ) + { + q1--, r1 += d; + while( r1 >= d && r1 < m ) + q1--, r1 += d; + } + r1 -= m; + + q0 = r1 / d1; + r0 = r1 - d1 * q0; + r0 <<= biH; + r0 |= ( X.p[i - 1] << biH ) >> biH; + + m = q0 * d0; + if( r0 < m ) + { + q0--, r0 += d; + while( r0 >= d && r0 < m ) + q0--, r0 += d; + } + r0 -= m; + + Z.p[i - t - 1] = ( q1 << biH ) | q0; +#endif /* POLARSSL_HAVE_UDBL && !64-bit Apple with Clang 5.0 */ + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MPI_CHK( mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MPI_CHK( 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( mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mpi_cmp_int( &X, 0 ) < 0 ) + { + MPI_CHK( mpi_copy( &T1, &Y ) ); + MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MPI_CHK( mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MPI_CHK( mpi_shift_r( &X, k ) ); + X.s = A->s; + MPI_CHK( mpi_copy( R, &X ) ); + + if( mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); + mpi_free( &T1 ); mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + + if( mpi_cmp_int( B, 0 ) < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); + + while( mpi_cmp_int( R, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( R, R, B ) ); + + while( mpi_cmp_mpi( R, B ) >= 0 ) + MPI_CHK( mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ) +{ + size_t i; + t_uint x, y, z; + + if( b == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( POLARSSL_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( t_uint *mm, const mpi *N ) +{ + t_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( mpi *A, const mpi *B, const mpi *N, t_uint mm, + const mpi *T ) +{ + size_t i, n, m; + t_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( 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( mpi *A, const mpi *N, t_uint mm, const mpi *T ) +{ + t_uint z = 1; + 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 mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + t_uint ei, mm, state; + mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos; + int neg; + + if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + if( mpi_cmp_int( E, 0 ) < 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mpi_init( &RR ); mpi_init( &T ); + mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mpi_msb( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if( wsize > POLARSSL_MPI_WINDOW_SIZE ) + wsize = POLARSSL_MPI_WINDOW_SIZE; + + j = N->n + 1; + MPI_CHK( mpi_grow( X, j ) ); + MPI_CHK( mpi_grow( &W[1], j ) ); + MPI_CHK( mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MPI_CHK( mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MPI_CHK( mpi_lset( &RR, 1 ) ); + MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); + MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mpi_cmp_mpi( A, N ) >= 0 ) + MPI_CHK( mpi_mod_mpi( &W[1], A, N ) ); + else + MPI_CHK( mpi_copy( &W[1], A ) ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MPI_CHK( 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 ); + + MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); + MPI_CHK( 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++ ) + { + MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); + MPI_CHK( 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( t_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; + MPI_CHK( mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mpi_free( &W[i] ); + + mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mpi_gcd( mpi *G, const mpi *A, const mpi *B ) +{ + int ret; + size_t lz, lzt; + mpi TG, TA, TB; + + mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB ); + + MPI_CHK( mpi_copy( &TA, A ) ); + MPI_CHK( mpi_copy( &TB, B ) ); + + lz = mpi_lsb( &TA ); + lzt = mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MPI_CHK( mpi_shift_r( &TA, lz ) ); + MPI_CHK( mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mpi_cmp_int( &TA, 0 ) != 0 ) + { + MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) ); + MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) ); + + if( mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) ); + MPI_CHK( mpi_shift_r( &TA, 1 ) ); + } + else + { + MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) ); + MPI_CHK( mpi_shift_r( &TB, 1 ) ); + } + } + + MPI_CHK( mpi_shift_l( &TB, lz ) ); + MPI_CHK( mpi_copy( G, &TB ) ); + +cleanup: + + mpi_free( &TG ); mpi_free( &TA ); 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 mpi_fill_random( mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + + if( size > POLARSSL_MPI_MAX_SIZE ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + MPI_CHK( f_rng( p_rng, buf, size ) ); + MPI_CHK( mpi_read_binary( X, buf, size ) ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ) +{ + int ret; + mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mpi_cmp_int( N, 0 ) <= 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 ); + mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV ); + mpi_init( &V1 ); mpi_init( &V2 ); + + MPI_CHK( mpi_gcd( &G, A, N ) ); + + if( mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MPI_CHK( mpi_mod_mpi( &TA, A, N ) ); + MPI_CHK( mpi_copy( &TU, &TA ) ); + MPI_CHK( mpi_copy( &TB, N ) ); + MPI_CHK( mpi_copy( &TV, N ) ); + + MPI_CHK( mpi_lset( &U1, 1 ) ); + MPI_CHK( mpi_lset( &U2, 0 ) ); + MPI_CHK( mpi_lset( &V1, 0 ) ); + MPI_CHK( mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &U1, 1 ) ); + MPI_CHK( mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &V1, 1 ) ); + MPI_CHK( mpi_shift_r( &V2, 1 ) ); + } + + if( mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) ); + MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) ); + MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mpi_cmp_int( &V1, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( &V1, &V1, N ) ); + + while( mpi_cmp_mpi( &V1, N ) >= 0 ) + MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) ); + + MPI_CHK( mpi_copy( X, &V1 ) ); + +cleanup: + + mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 ); + mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV ); + mpi_free( &V1 ); mpi_free( &V2 ); + + return( ret ); +} + +#if defined(POLARSSL_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 + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mpi *X ) +{ + int ret = 0; + size_t i; + t_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, n, s; + mpi W, R, T, A, RR; + + mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A ); + mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MPI_CHK( mpi_sub_int( &W, X, 1 ) ); + s = mpi_lsb( &W ); + MPI_CHK( mpi_copy( &R, &W ) ); + MPI_CHK( mpi_shift_r( &R, s ) ); + + i = mpi_msb( 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 + */ + + count = 0; + do { + MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mpi_msb( &A ); + k = mpi_msb( &W ); + if (j > k) { + MPI_CHK( mpi_shift_r( &A, j - k ) ); + } + + if (count++ > 30) { + return POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + } + + } while ( (mpi_cmp_mpi( &A, &W ) >= 0) || + (mpi_cmp_int( &A, 1 ) <= 0) ); + + /* + * A = A^R mod |X| + */ + MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mpi_cmp_mpi( &A, &W ) == 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MPI_CHK( mpi_mul_mpi( &T, &A, &A ) ); + MPI_CHK( mpi_mod_mpi( &A, &T, X ) ); + + if( mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mpi_cmp_mpi( &A, &W ) != 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A ); + mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mpi_is_prime( mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mpi XX; + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mpi_cmp_int( &XX, 0 ) == 0 || + mpi_cmp_int( &XX, 1 ) == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + + if( 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 mpi_gen_prime( 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; + t_uint r; + mpi Y; + + if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + + k = mpi_msb( X ); + if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits + 1 ) ); + + mpi_set_bit( X, nbits-1, 1 ); + + X->p[0] |= 1; + + if( dh_flag == 0 ) + { + while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MPI_CHK( 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; + + MPI_CHK( mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MPI_CHK( mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MPI_CHK( mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MPI_CHK( mpi_copy( &Y, X ) ); + MPI_CHK( 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 != POLARSSL_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. + */ + MPI_CHK( mpi_add_int( X, X, 12 ) ); + MPI_CHK( mpi_add_int( &Y, &Y, 6 ) ); + } + } + +cleanup: + + mpi_free( &Y ); + + return( ret ); +} + +#endif /* POLARSSL_GENPRIME */ + +#if defined(POLARSSL_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 mpi_self_test( int verbose ) +{ + int ret, i; + mpi A, E, N, X, Y, U, V; + + mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X ); + mpi_init( &Y ); mpi_init( &U ); mpi_init( &V ); + + MPI_CHK( mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MPI_CHK( mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MPI_CHK( mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MPI_CHK( mpi_mul_mpi( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #1 (mul_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MPI_CHK( mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #2 (div_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 || + mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #3 (exp_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + MPI_CHK( mpi_inv_mod( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #4 (inv_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) ); + MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MPI_CHK( mpi_gcd( &A, &X, &Y ) ); + + if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + polarssl_printf( "Unexpected error, return code = %08X\n", ret ); + + mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X ); + mpi_free( &Y ); mpi_free( &U ); mpi_free( &V ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_BIGNUM_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/blowfish.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/blowfish.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,658 @@ +/* + * Blowfish implementation + * + * Copyright (C) 2012-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_BLOWFISH_C) + +#include "polarssl/blowfish.h" + +#include <string.h> + +#if !defined(POLARSSL_BLOWFISH_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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[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( 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( blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < 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[BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 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 blowfish_init( blowfish_context *ctx ) +{ + memset( ctx, 0, sizeof( blowfish_context ) ); +} + +void blowfish_free( blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + + if( keysize < BLOWFISH_MIN_KEY || keysize > BLOWFISH_MAX_KEY || + ( keysize % 8 ) ) + { + return( POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH ); + } + + keysize >>= 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 < BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keysize ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < 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 blowfish_crypt_ecb( blowfish_context *ctx, + int mode, + const unsigned char input[BLOWFISH_BLOCKSIZE], + unsigned char output[BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + + GET_UINT32_BE( X0, input, 0 ); + GET_UINT32_BE( X1, input, 4 ); + + if( mode == BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + PUT_UINT32_BE( X0, output, 0 ); + PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int blowfish_crypt_cbc( blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[BLOWFISH_BLOCKSIZE]; + + if( length % BLOWFISH_BLOCKSIZE ) + return( POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, BLOWFISH_BLOCKSIZE ); + blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, BLOWFISH_BLOCKSIZE ); + + input += BLOWFISH_BLOCKSIZE; + output += BLOWFISH_BLOCKSIZE; + length -= BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, BLOWFISH_BLOCKSIZE ); + + input += BLOWFISH_BLOCKSIZE; + output += BLOWFISH_BLOCKSIZE; + length -= BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int blowfish_crypt_cfb64( blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int blowfish_crypt_ctr( blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[BLOWFISH_BLOCKSIZE], + unsigned char stream_block[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* POLARSSL_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 /* !POLARSSL_BLOWFISH_ALT */ +#endif /* POLARSSL_BLOWFISH_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/camellia.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/camellia.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1073 @@ +/* + * Camellia implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CAMELLIA_C) + +#include "polarssl/camellia.h" + +#if defined(POLARSSL_SELF_TEST) +#include <string.h> +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +#if !defined(POLARSSL_CAMELLIA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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(POLARSSL_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 /* POLARSSL_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 /* POLARSSL_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 camellia_init( camellia_context *ctx ) +{ + memset( ctx, 0, sizeof( camellia_context ) ); +} + +void camellia_free( camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + 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( keysize ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH ); + } + + for( i = 0; i < keysize / 8; ++i ) + t[i] = key[i]; + + if( keysize == 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( keysize > 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( keysize > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keysize > 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 camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + int idx, ret; + size_t i; + camellia_context cty; + uint32_t *RK; + uint32_t *SK; + + camellia_init( &cty ); + + /* Also checks keysize */ + if( ( ret = camellia_setkey_enc( &cty, key, keysize ) ) != 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: + camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int camellia_crypt_ecb( 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(POLARSSL_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int camellia_crypt_cbc( 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( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + 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] ); + + camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int camellia_crypt_cfb128( 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 == CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + camellia_crypt_ecb( ctx, 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 ) + camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int camellia_crypt_ctr( 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 ) { + camellia_crypt_ecb( ctx, 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 /* POLARSSL_CIPHER_MODE_CTR */ +#endif /* !POLARSSL_CAMELLIA_ALT */ + +#if defined(POLARSSL_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(POLARSSL_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 /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_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 /* POLARSSL_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int 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(POLARSSL_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + + camellia_context ctx; + + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + polarssl_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == 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 == CAMELLIA_DECRYPT ) { + 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 { /* CAMELLIA_ENCRYPT */ + 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 ); + } + + camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + polarssl_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == 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 == CAMELLIA_DECRYPT ) { + camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + camellia_setkey_enc( &ctx, key, 128 ); + + if( v == CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_CAMELLIA_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ccm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ccm.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,459 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright (C) 2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CCM_C) + +#include "polarssl/ccm.h" + +#include <string.h> + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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 + */ +int ccm_init( ccm_context *ctx, cipher_id_t cipher, + const unsigned char *key, unsigned int keysize ) +{ + int ret; + const cipher_info_t *cipher_info; + + memset( ctx, 0, sizeof( ccm_context ) ); + + cipher_init( &ctx->cipher_ctx ); + + cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + cipher_free( &ctx->cipher_ctx ); + + if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize, + POLARSSL_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void ccm_free( ccm_context *ctx ) +{ + cipher_free( &ctx->cipher_ctx ); + polarssl_zeroize( ctx, sizeof( 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 = 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 = 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( 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 = 16 - 1 - iv_len; + 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( POLARSSL_ERR_CCM_BAD_INPUT ); + + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + if( add_len > 0xFF00 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + /* + * 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( POLARSSL_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 ) + { + unsigned char 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 ccm_encrypt_and_tag( 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 ccm_auth_decrypt( 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 ) + { + polarssl_zeroize( output, length ); + return( POLARSSL_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_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 ccm_self_test( int verbose ) +{ + ccm_context ctx; + unsigned char out[32]; + size_t i; + int ret; + + if( ccm_init( &ctx, POLARSSL_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + ret = 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + ret = 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + ccm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */ + +#endif /* POLARSSL_CCM_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/certs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/certs.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,308 @@ +/* + * X.509 test certificates + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CERTS_C) + +#if defined(POLARSSL_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 test_ca_crt_ec[] = TEST_CA_CRT_EC; + +const char 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 test_ca_pwd_ec[] = "PolarSSLTest"; + +const char 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 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 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 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"; +#else +#define TEST_CA_CRT_EC +#endif /* POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_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 test_ca_crt_rsa[] = TEST_CA_CRT_RSA; + +const char 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 test_ca_pwd_rsa[] = "PolarSSLTest"; + +const char 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 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 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 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"; +#else +#define TEST_CA_CRT_RSA +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_DHM_C) +const char 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"; +#endif + +/* Concatenation of all available CA certificates */ +const char test_ca_list[] = TEST_CA_CRT_RSA TEST_CA_CRT_EC; + +#if defined(POLARSSL_RSA_C) +const char *test_ca_crt = test_ca_crt_rsa; +const char *test_ca_key = test_ca_key_rsa; +const char *test_ca_pwd = test_ca_pwd_rsa; +const char *test_srv_crt = test_srv_crt_rsa; +const char *test_srv_key = test_srv_key_rsa; +const char *test_cli_crt = test_cli_crt_rsa; +const char *test_cli_key = test_cli_key_rsa; +#else /* ! POLARSSL_RSA_C, so POLARSSL_ECDSA_C */ +const char *test_ca_crt = test_ca_crt_ec; +const char *test_ca_key = test_ca_key_ec; +const char *test_ca_pwd = test_ca_pwd_ec; +const char *test_srv_crt = test_srv_crt_ec; +const char *test_srv_key = test_srv_key_ec; +const char *test_cli_crt = test_cli_crt_ec; +const char *test_cli_key = test_cli_key_ec; +#endif /* POLARSSL_RSA_C */ + +#endif /* POLARSSL_CERTS_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/cipher.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/cipher.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,917 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CIPHER_C) + +#include "polarssl/cipher.h" +#include "polarssl/cipher_wrap.h" + +#include <stdlib.h> +#include <string.h> + +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + +#if defined(POLARSSL_CCM_C) +#include "polarssl/ccm.h" +#endif + +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) +#define POLARSSL_CIPHER_MODE_STREAM +#endif + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static int supported_init = 0; + +const int *cipher_list( void ) +{ + const cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = cipher_definitions; + type = supported_ciphers; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( supported_ciphers ); +} + +const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type ) +{ + const cipher_definition_t *def; + + for( def = cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const cipher_info_t *cipher_info_from_string( const char *cipher_name ) +{ + const cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = cipher_definitions; def->info != NULL; def++ ) + if( ! strcasecmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id, + int key_length, + const cipher_mode_t mode ) +{ + const cipher_definition_t *def; + + for( def = cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_length == (unsigned) key_length && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void cipher_init( cipher_context_t *ctx ) +{ + memset( ctx, 0, sizeof( cipher_context_t ) ); +} + +void cipher_free( cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + polarssl_zeroize( ctx, sizeof(cipher_context_t) ); +} + +int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( POLARSSL_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(POLARSSL_CIPHER_PADDING_PKCS7) + (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_PKCS7 ); +#else + (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_NONE ); +#endif +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +int cipher_free_ctx( cipher_context_t *ctx ) +{ + cipher_free( ctx ); + + return( 0 ); +} +#endif + +int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, + int key_length, const operation_t operation ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & POLARSSL_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_length != key_length ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_length = key_length; + ctx->operation = operation; + + /* + * For CFB and CTR mode always use the encryption key schedule + */ + if( POLARSSL_ENCRYPT == operation || + POLARSSL_MODE_CFB == ctx->cipher_info->mode || + POLARSSL_MODE_CTR == ctx->cipher_info->mode ) + { + return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_length ); + } + + if( POLARSSL_DECRYPT == operation ) + return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_length ); + + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int cipher_set_iv( 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( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > POLARSSL_MAX_IV_LENGTH ) + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & POLARSSL_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( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + + return( 0 ); +} + +int cipher_reset( cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(POLARSSL_GCM_C) +int cipher_update_ad( cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + return gcm_starts( (gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ); + } + + return( 0 ); +} +#endif /* POLARSSL_GCM_C */ + +int cipher_update( 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( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = 0; + + if( ctx->cipher_info->mode == POLARSSL_MODE_ECB ) + { + if( ilen != cipher_get_block_size( ctx ) ) + return( POLARSSL_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(POLARSSL_GCM_C) + if( ctx->cipher_info->mode == POLARSSL_MODE_GCM ) + { + *olen = ilen; + return gcm_update( (gcm_context *) ctx->cipher_ctx, ilen, input, + output ); + } +#endif + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(POLARSSL_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == POLARSSL_DECRYPT && + ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) || + ( ctx->operation == POLARSSL_ENCRYPT && + ilen + ctx->unprocessed_len < 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 = 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, cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += cipher_get_block_size( ctx ); + output += 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 % cipher_get_block_size( ctx ); + if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT ) + copy_len = 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 /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == POLARSSL_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 /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == POLARSSL_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 /* POLARSSL_CIPHER_MODE_CTR */ + +#if defined(POLARSSL_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == POLARSSL_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* POLARSSL_CIPHER_MODE_STREAM */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) +#if defined(POLARSSL_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( POLARSSL_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( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* POLARSSL_CIPHER_PADDING_PKCS7 */ + +#if defined(POLARSSL_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( POLARSSL_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( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(POLARSSL_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( POLARSSL_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( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(POLARSSL_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( POLARSSL_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 /* POLARSSL_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in 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( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + +int cipher_finish( cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + + if( POLARSSL_MODE_CFB == ctx->cipher_info->mode || + POLARSSL_MODE_CTR == ctx->cipher_info->mode || + POLARSSL_MODE_GCM == ctx->cipher_info->mode || + POLARSSL_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if( POLARSSL_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(POLARSSL_CIPHER_MODE_CBC) + if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( POLARSSL_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( 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( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( POLARSSL_DECRYPT == ctx->operation ) + return ctx->get_padding( output, cipher_get_block_size( ctx ), + olen ); + + /* Set output size for encryption */ + *olen = cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) +int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ) +{ + if( NULL == ctx || + POLARSSL_MODE_CBC != ctx->cipher_info->mode ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + switch( mode ) + { +#if defined(POLARSSL_CIPHER_PADDING_PKCS7) + case POLARSSL_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS) + case POLARSSL_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN) + case POLARSSL_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(POLARSSL_CIPHER_PADDING_ZEROS) + case POLARSSL_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case POLARSSL_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + +#if defined(POLARSSL_GCM_C) +int cipher_write_tag( cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( POLARSSL_ENCRYPT != ctx->operation ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + return gcm_finish( (gcm_context *) ctx->cipher_ctx, tag, tag_len ); + + return( 0 ); +} + +int cipher_check_tag( cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + + if( NULL == ctx || NULL == ctx->cipher_info || + POLARSSL_DECRYPT != ctx->operation ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag_len > sizeof( check_tag ) ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = gcm_finish( (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( POLARSSL_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } + + return( 0 ); +} +#endif /* POLARSSL_GCM_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int cipher_crypt( 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 = cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int cipher_auth_encrypt( 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(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( gcm_crypt_and_tag( ctx->cipher_ctx, GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif /* POLARSSL_GCM_C */ +#if defined(POLARSSL_CCM_C) + if( POLARSSL_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* POLARSSL_CCM_C */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int cipher_auth_decrypt( 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(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == POLARSSL_ERR_GCM_AUTH_FAILED ) + ret = POLARSSL_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* POLARSSL_GCM_C */ +#if defined(POLARSSL_CCM_C) + if( POLARSSL_MODE_CCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == POLARSSL_ERR_CCM_AUTH_FAILED ) + ret = POLARSSL_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* POLARSSL_CCM_C */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int cipher_self_test( int verbose ) +{ + ((void) verbose); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_CIPHER_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/cipher_wrap.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/cipher_wrap.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1443 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CIPHER_C) + +#include "polarssl/cipher_wrap.h" + +#if defined(POLARSSL_AES_C) +#include "polarssl/aes.h" +#endif + +#if defined(POLARSSL_ARC4_C) +#include "polarssl/arc4.h" +#endif + +#if defined(POLARSSL_CAMELLIA_C) +#include "polarssl/camellia.h" +#endif + +#if defined(POLARSSL_DES_C) +#include "polarssl/des.h" +#endif + +#if defined(POLARSSL_BLOWFISH_C) +#include "polarssl/blowfish.h" +#endif + +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + +#if defined(POLARSSL_CCM_C) +#include "polarssl/ccm.h" +#endif + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#include <string.h> +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(POLARSSL_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( gcm_context ) ); +} + +static void gcm_ctx_free( void *ctx ) +{ + gcm_free( ctx ); + polarssl_free( ctx ); +} +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( ccm_context ) ); +} + +static void ccm_ctx_free( void *ctx ) +{ + ccm_free( ctx ); + polarssl_free( ctx ); +} +#endif /* POLARSSL_CCM_C */ + +#if defined(POLARSSL_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return aes_crypt_ecb( (aes_context *) ctx, operation, input, output ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_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 aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return aes_setkey_dec( (aes_context *) ctx, key, key_length ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return aes_setkey_enc( (aes_context *) ctx, key, key_length ); +} + +static void * aes_ctx_alloc( void ) +{ + aes_context *aes = polarssl_malloc( sizeof( aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + aes_free( (aes_context *) ctx ); + polarssl_free( ctx ); +} + +static const cipher_base_t aes_info = { + POLARSSL_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(POLARSSL_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const cipher_info_t aes_128_ecb_info = { + POLARSSL_CIPHER_AES_128_ECB, + POLARSSL_MODE_ECB, + 128, + "AES-128-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_192_ecb_info = { + POLARSSL_CIPHER_AES_192_ECB, + POLARSSL_MODE_ECB, + 192, + "AES-192-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_256_ecb_info = { + POLARSSL_CIPHER_AES_256_ECB, + POLARSSL_MODE_ECB, + 256, + "AES-256-ECB", + 16, + 0, + 16, + &aes_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const cipher_info_t aes_128_cbc_info = { + POLARSSL_CIPHER_AES_128_CBC, + POLARSSL_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_192_cbc_info = { + POLARSSL_CIPHER_AES_192_CBC, + POLARSSL_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_256_cbc_info = { + POLARSSL_CIPHER_AES_256_CBC, + POLARSSL_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +static const cipher_info_t aes_128_cfb128_info = { + POLARSSL_CIPHER_AES_128_CFB128, + POLARSSL_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_192_cfb128_info = { + POLARSSL_CIPHER_AES_192_CFB128, + POLARSSL_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_256_cfb128_info = { + POLARSSL_CIPHER_AES_256_CFB128, + POLARSSL_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +static const cipher_info_t aes_128_ctr_info = { + POLARSSL_CIPHER_AES_128_CTR, + POLARSSL_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_192_ctr_info = { + POLARSSL_CIPHER_AES_192_CTR, + POLARSSL_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const cipher_info_t aes_256_ctr_info = { + POLARSSL_CIPHER_AES_256_CTR, + POLARSSL_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#if defined(POLARSSL_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_AES, + key, key_length ); +} + +static const cipher_base_t gcm_aes_info = { + POLARSSL_CIPHER_ID_AES, + NULL, +#if defined(POLARSSL_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const cipher_info_t aes_128_gcm_info = { + POLARSSL_CIPHER_AES_128_GCM, + POLARSSL_MODE_GCM, + 128, + "AES-128-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const cipher_info_t aes_192_gcm_info = { + POLARSSL_CIPHER_AES_192_GCM, + POLARSSL_MODE_GCM, + 192, + "AES-192-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const cipher_info_t aes_256_gcm_info = { + POLARSSL_CIPHER_AES_256_GCM, + POLARSSL_MODE_GCM, + 256, + "AES-256-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_AES, + key, key_length ); +} + +static const cipher_base_t ccm_aes_info = { + POLARSSL_CIPHER_ID_AES, + NULL, +#if defined(POLARSSL_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const cipher_info_t aes_128_ccm_info = { + POLARSSL_CIPHER_AES_128_CCM, + POLARSSL_MODE_CCM, + 128, + "AES-128-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const cipher_info_t aes_192_ccm_info = { + POLARSSL_CIPHER_AES_192_CCM, + POLARSSL_MODE_CCM, + 192, + "AES-192-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const cipher_info_t aes_256_ccm_info = { + POLARSSL_CIPHER_AES_256_CCM, + POLARSSL_MODE_CCM, + 256, + "AES-256-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* POLARSSL_CCM_C */ + +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return camellia_crypt_ecb( (camellia_context *) ctx, operation, input, + output ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_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 camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return camellia_setkey_dec( (camellia_context *) ctx, key, key_length ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return camellia_setkey_enc( (camellia_context *) ctx, key, key_length ); +} + +static void * camellia_ctx_alloc( void ) +{ + camellia_context *ctx; + ctx = polarssl_malloc( sizeof( camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + camellia_free( (camellia_context *) ctx ); + polarssl_free( ctx ); +} + +static const cipher_base_t camellia_info = { + POLARSSL_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(POLARSSL_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const cipher_info_t camellia_128_ecb_info = { + POLARSSL_CIPHER_CAMELLIA_128_ECB, + POLARSSL_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_192_ecb_info = { + POLARSSL_CIPHER_CAMELLIA_192_ECB, + POLARSSL_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_256_ecb_info = { + POLARSSL_CIPHER_CAMELLIA_256_ECB, + POLARSSL_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 16, + 0, + 16, + &camellia_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const cipher_info_t camellia_128_cbc_info = { + POLARSSL_CIPHER_CAMELLIA_128_CBC, + POLARSSL_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_192_cbc_info = { + POLARSSL_CIPHER_CAMELLIA_192_CBC, + POLARSSL_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_256_cbc_info = { + POLARSSL_CIPHER_CAMELLIA_256_CBC, + POLARSSL_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +static const cipher_info_t camellia_128_cfb128_info = { + POLARSSL_CIPHER_CAMELLIA_128_CFB128, + POLARSSL_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_192_cfb128_info = { + POLARSSL_CIPHER_CAMELLIA_192_CFB128, + POLARSSL_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_256_cfb128_info = { + POLARSSL_CIPHER_CAMELLIA_256_CFB128, + POLARSSL_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +static const cipher_info_t camellia_128_ctr_info = { + POLARSSL_CIPHER_CAMELLIA_128_CTR, + POLARSSL_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_192_ctr_info = { + POLARSSL_CIPHER_CAMELLIA_192_CTR, + POLARSSL_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const cipher_info_t camellia_256_ctr_info = { + POLARSSL_CIPHER_CAMELLIA_256_CTR, + POLARSSL_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#if defined(POLARSSL_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA, + key, key_length ); +} + +static const cipher_base_t gcm_camellia_info = { + POLARSSL_CIPHER_ID_CAMELLIA, + NULL, +#if defined(POLARSSL_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const cipher_info_t camellia_128_gcm_info = { + POLARSSL_CIPHER_CAMELLIA_128_GCM, + POLARSSL_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const cipher_info_t camellia_192_gcm_info = { + POLARSSL_CIPHER_CAMELLIA_192_GCM, + POLARSSL_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const cipher_info_t camellia_256_gcm_info = { + POLARSSL_CIPHER_CAMELLIA_256_GCM, + POLARSSL_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA, + key, key_length ); +} + +static const cipher_base_t ccm_camellia_info = { + POLARSSL_CIPHER_ID_CAMELLIA, + NULL, +#if defined(POLARSSL_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const cipher_info_t camellia_128_ccm_info = { + POLARSSL_CIPHER_CAMELLIA_128_CCM, + POLARSSL_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const cipher_info_t camellia_192_ccm_info = { + POLARSSL_CIPHER_CAMELLIA_192_CCM, + POLARSSL_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const cipher_info_t camellia_256_ccm_info = { + POLARSSL_CIPHER_CAMELLIA_256_CCM, + POLARSSL_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* POLARSSL_CCM_C */ + +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return des_crypt_ecb( (des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return des3_crypt_ecb( (des3_context *) ctx, input, output ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des_setkey_dec( (des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des_setkey_enc( (des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set2key_dec( (des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set2key_enc( (des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set3key_dec( (des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set3key_enc( (des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + des_context *des = polarssl_malloc( sizeof( des_context ) ); + + if( des == NULL ) + return( NULL ); + + des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + des_free( (des_context *) ctx ); + polarssl_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + des3_context *des3; + des3 = polarssl_malloc( sizeof( des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + des3_free( (des3_context *) ctx ); + polarssl_free( ctx ); +} + +static const cipher_base_t des_info = { + POLARSSL_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(POLARSSL_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const cipher_info_t des_ecb_info = { + POLARSSL_CIPHER_DES_ECB, + POLARSSL_MODE_ECB, + POLARSSL_KEY_LENGTH_DES, + "DES-ECB", + 8, + 0, + 8, + &des_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const cipher_info_t des_cbc_info = { + POLARSSL_CIPHER_DES_CBC, + POLARSSL_MODE_CBC, + POLARSSL_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +static const cipher_base_t des_ede_info = { + POLARSSL_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(POLARSSL_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const cipher_info_t des_ede_ecb_info = { + POLARSSL_CIPHER_DES_EDE_ECB, + POLARSSL_MODE_ECB, + POLARSSL_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 8, + 0, + 8, + &des_ede_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const cipher_info_t des_ede_cbc_info = { + POLARSSL_CIPHER_DES_EDE_CBC, + POLARSSL_MODE_CBC, + POLARSSL_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +static const cipher_base_t des_ede3_info = { + POLARSSL_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(POLARSSL_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const cipher_info_t des_ede3_ecb_info = { + POLARSSL_CIPHER_DES_EDE3_ECB, + POLARSSL_MODE_ECB, + POLARSSL_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 8, + 0, + 8, + &des_ede3_info +}; +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const cipher_info_t des_ede3_cbc_info = { + POLARSSL_CIPHER_DES_EDE3_CBC, + POLARSSL_MODE_CBC, + POLARSSL_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return blowfish_crypt_ecb( (blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return blowfish_crypt_cbc( (blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return blowfish_crypt_cfb64( (blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_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 blowfish_crypt_ctr( (blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return blowfish_setkey( (blowfish_context *) ctx, key, key_length ); +} + +static void * blowfish_ctx_alloc( void ) +{ + blowfish_context *ctx; + ctx = polarssl_malloc( sizeof( blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + blowfish_free( (blowfish_context *) ctx ); + polarssl_free( ctx ); +} + +static const cipher_base_t blowfish_info = { + POLARSSL_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(POLARSSL_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +static const cipher_info_t blowfish_ecb_info = { + POLARSSL_CIPHER_BLOWFISH_ECB, + POLARSSL_MODE_ECB, + 128, + "BLOWFISH-ECB", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const cipher_info_t blowfish_cbc_info = { + POLARSSL_CIPHER_BLOWFISH_CBC, + POLARSSL_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +static const cipher_info_t blowfish_cfb64_info = { + POLARSSL_CIPHER_BLOWFISH_CFB64, + POLARSSL_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +static const cipher_info_t blowfish_ctr_info = { + POLARSSL_CIPHER_BLOWFISH_CTR, + POLARSSL_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* POLARSSL_CIPHER_MODE_CTR */ +#endif /* POLARSSL_BLOWFISH_C */ + +#if defined(POLARSSL_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( arc4_crypt( (arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + /* we get key_length in bits, arc4 expects it in bytes */ + if( key_length % 8 != 0 ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + arc4_setup( (arc4_context *) ctx, key, key_length / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + arc4_context *ctx; + ctx = polarssl_malloc( sizeof( arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + arc4_free( (arc4_context *) ctx ); + polarssl_free( ctx ); +} + +static const cipher_base_t arc4_base_info = { + POLARSSL_CIPHER_ID_ARC4, + NULL, +#if defined(POLARSSL_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +static const cipher_info_t arc4_128_info = { + POLARSSL_CIPHER_ARC4_128, + POLARSSL_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_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_length ) +{ + ((void) ctx); + ((void) key); + ((void) key_length); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const cipher_base_t null_base_info = { + POLARSSL_CIPHER_ID_NULL, + NULL, +#if defined(POLARSSL_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const cipher_info_t null_cipher_info = { + POLARSSL_CIPHER_NULL, + POLARSSL_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ + +const cipher_definition_t cipher_definitions[] = +{ +#if defined(POLARSSL_AES_C) + { POLARSSL_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { POLARSSL_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { POLARSSL_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { POLARSSL_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { POLARSSL_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + { POLARSSL_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { POLARSSL_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { POLARSSL_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + { POLARSSL_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { POLARSSL_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { POLARSSL_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(POLARSSL_GCM_C) + { POLARSSL_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { POLARSSL_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { POLARSSL_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(POLARSSL_CCM_C) + { POLARSSL_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { POLARSSL_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { POLARSSL_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_ARC4_C) + { POLARSSL_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(POLARSSL_BLOWFISH_C) + { POLARSSL_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + { POLARSSL_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + { POLARSSL_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* POLARSSL_BLOWFISH_C */ + +#if defined(POLARSSL_CAMELLIA_C) + { POLARSSL_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { POLARSSL_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { POLARSSL_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + { POLARSSL_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + { POLARSSL_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(POLARSSL_GCM_C) + { POLARSSL_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { POLARSSL_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { POLARSSL_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(POLARSSL_CCM_C) + { POLARSSL_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) + { POLARSSL_CIPHER_DES_ECB, &des_ecb_info }, + { POLARSSL_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { POLARSSL_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_DES_CBC, &des_cbc_info }, + { POLARSSL_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { POLARSSL_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) + { POLARSSL_CIPHER_NULL, &null_cipher_info }, +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ + + { POLARSSL_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS sizeof cipher_definitions / sizeof cipher_definitions[0] +int supported_ciphers[NUM_CIPHERS]; + +#endif /* POLARSSL_CIPHER_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ctr_drbg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ctr_drbg.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,558 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CTR_DRBG_C) + +#include "polarssl/ctr_drbg.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST + * tests to succeed (which require known length fixed entropy) + */ +int ctr_drbg_init_entropy_len( + 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[CTR_DRBG_KEYSIZE]; + + memset( ctx, 0, sizeof(ctr_drbg_context) ); + memset( key, 0, CTR_DRBG_KEYSIZE ); + + aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->entropy_len = entropy_len; + ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS ); + + if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int ctr_drbg_init( ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len, + CTR_DRBG_ENTROPY_LEN ) ); +} + +void ctr_drbg_free( ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + + aes_free( &ctx->aes_ctx ); + polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) ); +} + +void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +void ctr_drbg_set_reseed_interval( 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[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[CTR_DRBG_SEEDLEN]; + unsigned char key[CTR_DRBG_KEYSIZE]; + unsigned char chain[CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + aes_context aes_ctx; + + int i, j; + size_t buf_len, use_len; + + if( data_len > CTR_DRBG_MAX_SEED_INPUT ) + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 ); + 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 + 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++ = CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS ); + + /* + * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ? + CTR_DRBG_BLOCKSIZE : use_len; + + aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain ); + } + + memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS ); + iv = tmp + CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) + { + aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv ); + memcpy( p, iv, CTR_DRBG_BLOCKSIZE ); + p += CTR_DRBG_BLOCKSIZE; + } + + aes_free( &aes_ctx ); + + return( 0 ); +} + +static int ctr_drbg_update_internal( ctr_drbg_context *ctx, + const unsigned char data[CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + + memset( tmp, 0, CTR_DRBG_SEEDLEN ); + + for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p ); + + p += CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS ); + memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE ); + + return( 0 ); +} + +void ctr_drbg_update( ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + unsigned char add_input[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 > CTR_DRBG_MAX_SEED_INPUT ) + add_len = CTR_DRBG_MAX_SEED_INPUT; + + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } +} + +int ctr_drbg_reseed( ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + + if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT ) + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, 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( POLARSSL_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 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; + ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng; + unsigned char add_input[CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > CTR_DRBG_MAX_REQUEST ) + return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > CTR_DRBG_MAX_INPUT ) + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = 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 = CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp ); + + use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? 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 ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 ); +} + +#if defined(POLARSSL_FS_IO) +int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path ) +{ + int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT ) + { + ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > CTR_DRBG_MAX_INPUT ) + { + fclose( f ); + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); + } + + fclose( f ); + + ctr_drbg_update( ctx, buf, n ); + + return( ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_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 ) \ + polarssl_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine + */ +int ctr_drbg_self_test( int verbose ) +{ + ctr_drbg_context ctx; + unsigned char buf[16]; + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + polarssl_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); + ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON ); + CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) ); + CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) ); + CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + polarssl_printf( " CTR_DRBG (PR = FALSE): " ); + + test_offset = 0; + CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); + CHK( ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( memcmp( buf, result_nopr, 16 ) ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_CTR_DRBG_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/debug.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/debug.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,360 @@ +/* + * Debugging routines + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_DEBUG_C) + +#include "polarssl/debug.h" + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#if !defined snprintf +#define snprintf _snprintf +#endif + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif +#endif /* _MSC_VER */ + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_snprintf snprintf +#endif + +static int debug_log_mode = POLARSSL_DEBUG_DFL_MODE; +static int debug_threshold = 0; + +void debug_set_log_mode( int log_mode ) +{ + debug_log_mode = log_mode; +} + +void debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +char *debug_fmt( const char *format, ... ) +{ + va_list argp; + static char str[512]; + int maxlen = sizeof( str ) - 1; + + va_start( argp, format ); + vsnprintf( str, maxlen, format, argp ); + va_end( argp ); + + str[maxlen] = '\0'; + return( str ); +} + +void debug_print_msg( const ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[512]; + int maxlen = sizeof( str ) - 1; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_RAW ) + { + ssl->f_dbg( ssl->p_dbg, level, text ); + return; + } + + polarssl_snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text ); + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); +} + +void debug_print_ret( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[512]; + int maxlen = sizeof( str ) - 1; + size_t idx = 0; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line ); + + polarssl_snprintf( str + idx, maxlen - idx, "%s() returned %d (-0x%04x)\n", + text, ret, -ret ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); +} + +void debug_print_buf( const ssl_context *ssl, int level, + const char *file, int line, const char *text, + unsigned char *buf, size_t len ) +{ + char str[512]; + char txt[17]; + size_t i, maxlen = sizeof( str ) - 1, idx = 0; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line ); + + polarssl_snprintf( str + idx, maxlen - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, 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 ) + { + polarssl_snprintf( str + idx, maxlen - idx, " %s\n", txt ); + ssl->f_dbg( ssl->p_dbg, level, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + } + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line ); + + idx += polarssl_snprintf( str + idx, maxlen - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += polarssl_snprintf( str + idx, maxlen - 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 += polarssl_snprintf( str + idx, maxlen - idx, " " ); + + polarssl_snprintf( str + idx, maxlen - idx, " %s\n", txt ); + ssl->f_dbg( ssl->p_dbg, level, str ); + } +} + +#if defined(POLARSSL_ECP_C) +void debug_print_ecp( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const ecp_point *X ) +{ + char str[512]; + int maxlen = sizeof( str ) - 1; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + polarssl_snprintf( str, maxlen, "%s(X)", text ); + str[maxlen] = '\0'; + debug_print_mpi( ssl, level, file, line, str, &X->X ); + + polarssl_snprintf( str, maxlen, "%s(Y)", text ); + str[maxlen] = '\0'; + debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_BIGNUM_C) +void debug_print_mpi( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mpi *X ) +{ + char str[512]; + int j, k, maxlen = sizeof( str ) - 1, zeros = 1; + size_t i, n, idx = 0; + + if( ssl->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(t_uint) << 3 ) - 1; j >= 0; j-- ) + if( ( ( X->p[n] >> j ) & 1 ) != 0 ) + break; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line ); + + polarssl_snprintf( str + idx, maxlen - idx, "value of '%s' (%d bits) is:\n", + text, (int) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); + + idx = 0; + for( i = n + 1, j = 0; i > 0; i-- ) + { + if( zeros && X->p[i - 1] == 0 ) + continue; + + for( k = sizeof( t_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 ) + { + polarssl_snprintf( str + idx, maxlen - idx, "\n" ); + ssl->f_dbg( ssl->p_dbg, level, str ); + idx = 0; + } + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line ); + } + + idx += polarssl_snprintf( str + idx, maxlen - idx, " %02x", (unsigned int) + ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); + + j++; + } + + } + + if( zeros == 1 ) + { + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + { + idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line ); + + } + idx += polarssl_snprintf( str + idx, maxlen - idx, " 00" ); + } + + polarssl_snprintf( str + idx, maxlen - idx, "\n" ); + ssl->f_dbg( ssl->p_dbg, level, str ); +} +#endif /* POLARSSL_BIGNUM_C */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +static void debug_print_pk( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const pk_context *pk ) +{ + size_t i; + pk_debug_item items[POLARSSL_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( pk_debug( pk, items ) != 0 ) + { + debug_print_msg( ssl, level, file, line, "invalid PK context" ); + return; + } + + for( i = 0; i < POLARSSL_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == POLARSSL_PK_DEBUG_NONE ) + return; + + polarssl_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == POLARSSL_PK_DEBUG_MPI ) + debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(POLARSSL_ECP_C) + if( items[i].type == POLARSSL_PK_DEBUG_ECP ) + debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_print_msg( ssl, level, file, line, "should not happen" ); + } +} + +void debug_print_crt( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const x509_crt *crt ) +{ + char str[1024], prefix[64]; + int i = 0, maxlen = sizeof( prefix ) - 1, idx = 0; + + if( ssl->f_dbg == NULL || crt == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + { + polarssl_snprintf( prefix, maxlen, "%s(%04d): ", file, line ); + prefix[maxlen] = '\0'; + } + else + prefix[0] = '\0'; + + maxlen = sizeof( str ) - 1; + + while( crt != NULL ) + { + char buf[1024]; + x509_crt_info( buf, sizeof( buf ) - 1, prefix, crt ); + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = polarssl_snprintf( str, maxlen, "%s(%04d): ", file, line ); + + polarssl_snprintf( str + idx, maxlen - idx, "%s #%d:\n%s", + text, ++i, buf ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#endif /* POLARSSL_DEBUG_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/des.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/des.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1057 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_DES_C) + +#include "polarssl/des.h" + +#include <string.h> + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +#if !defined(POLARSSL_DES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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 des_init( des_context *ctx ) +{ + memset( ctx, 0, sizeof( des_context ) ); +} + +void des_free( des_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( des_context ) ); +} + +void des3_init( des3_context *ctx ) +{ + memset( ctx, 0, sizeof( des3_context ) ); +} + +void des3_free( des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( 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 des_key_set_parity( unsigned char key[DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < 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 des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < 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][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 des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +static void des_setkey( uint32_t SK[32], const unsigned char key[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); + } +} + +/* + * DES key schedule (56-bit, encryption) + */ +int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) +{ + des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) +{ + int i; + + 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[DES_KEY_SIZE*2] ) +{ + int i; + + des_setkey( esk, key ); + 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 des3_set2key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + polarssl_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int des3_set2key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + polarssl_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; + + des_setkey( esk, key ); + des_setkey( dsk + 32, key + 8 ); + 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 des3_set3key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + polarssl_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int des3_set3key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + polarssl_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +int des_crypt_ecb( 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 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int des_crypt_cbc( 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( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + des_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + 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 /* POLARSSL_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +int des3_crypt_ecb( 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 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int des3_crypt_cbc( 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( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + des3_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + 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 /* POLARSSL_CIPHER_MODE_CBC */ + +#endif /* !POLARSSL_DES_ALT */ + +#if defined(POLARSSL_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(POLARSSL_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 /* POLARSSL_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + des_context ctx; + des3_context ctx3; + unsigned char buf[8]; +#if defined(POLARSSL_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + des_init( &ctx ); + des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + des_crypt_ecb( &ctx, buf, buf ); + else + des3_crypt_ecb( &ctx3, buf, buf ); + } + + if( ( v == DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == 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: + des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + if( v == DES_DECRYPT ) + { + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + } + } + else + { + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + 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 == DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + des_free( &ctx ); + des3_free( &ctx3 ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_DES_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/dhm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/dhm.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,614 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * Reference: + * + * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12) + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_DHM_C) + +#include "polarssl/dhm.h" + +#include <string.h> + +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_ASN1_PARSE_C) +#include "polarssl/asn1.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#include <stdio.h> +#define polarssl_printf printf +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * helper to validate the mpi size and import it + */ +static int dhm_read_bignum( mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 ) + return( POLARSSL_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 mpi *param, const mpi *P ) +{ + mpi L, U; + int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA; + + mpi_init( &L ); mpi_init( &U ); + + MPI_CHK( mpi_lset( &L, 2 ) ); + MPI_CHK( mpi_sub_int( &U, P, 2 ) ); + + if( mpi_cmp_mpi( param, &L ) >= 0 && + mpi_cmp_mpi( param, &U ) <= 0 ) + { + ret = 0; + } + +cleanup: + mpi_free( &L ); mpi_free( &U ); + return( ret ); +} + +void dhm_init( dhm_context *ctx ) +{ + memset( ctx, 0, sizeof( dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int dhm_read_params( 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 = mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int dhm_make_params( 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( mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + /* + * Generate X as large as possible ( < P ) + */ + do + { + mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + /* + * Calculate GX = G^X mod P + */ + MPI_CHK( 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) \ + MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \ + *p++ = (unsigned char)( n >> 8 ); \ + *p++ = (unsigned char)( n ); p += n; + + n1 = mpi_size( &ctx->P ); + n2 = mpi_size( &ctx->G ); + n3 = 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( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret ); + + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int dhm_read_public( dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret; + + if( ctx == NULL || ilen < 1 || ilen > ctx->len ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int dhm_make_public( 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( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + /* + * generate X and calculate GX = G^X mod P + */ + do + { + mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + MPI_CHK( 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 ); + + MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + + if( ret != 0 ) + return( POLARSSL_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( 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( mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MPI_CHK( mpi_copy( &ctx->pX, &ctx->X ) ); + MPI_CHK( mpi_lset( &ctx->Vi, 1 ) ); + MPI_CHK( 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( mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MPI_CHK( 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 + { + mpi_fill_random( &ctx->Vi, mpi_size( &ctx->P ), f_rng, p_rng ); + + while( mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &ctx->Vi, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); + + /* Vf = Vi^-X mod P */ + MPI_CHK( mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); + MPI_CHK( 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 dhm_calc_secret( dhm_context *ctx, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mpi GYb; + + if( ctx == NULL || *olen < ctx->len ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MPI_CHK( mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MPI_CHK( mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MPI_CHK( mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MPI_CHK( mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MPI_CHK( mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MPI_CHK( mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + *olen = mpi_size( &ctx->K ); + + MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mpi_free( &GYb ); + + if( ret != 0 ) + return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void dhm_free( dhm_context *ctx ) +{ + mpi_free( &ctx->pX); mpi_free( &ctx->Vf ); mpi_free( &ctx->Vi ); + mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY ); + mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G ); + mpi_free( &ctx->P ); + + polarssl_zeroize( ctx, sizeof( dhm_context ) ); +} + +#if defined(POLARSSL_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret; + size_t len; + unsigned char *p, *end; +#if defined(POLARSSL_PEM_PARSE_C) + pem_context pem; + + pem_init( &pem ); + + ret = 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 != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* POLARSSL_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + end = p + len; + + if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + if( p != end ) + { + /* this might be the optional privateValueLength; If so, we + can cleanly discard it; */ + mpi rec; + mpi_init( &rec ); + ret = asn1_get_mpi( &p, end, &rec ); + mpi_free( &rec ); + if ( ret != 0 ) + { + ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + if ( p != end ) + { + ret = POLARSSL_ERR_DHM_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH; + goto exit; + } + } + + ret = 0; + + dhm->len = mpi_size( &dhm->P ); + +exit: +#if defined(POLARSSL_PEM_PARSE_C) + pem_free( &pem ); +#endif + if( ret != 0 ) + dhm_free( dhm ); + + return( ret ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load all data from a file into a given buffer. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( POLARSSL_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = polarssl_malloc( *n + 1 ) ) == NULL ) + { + fclose( f ); + return( POLARSSL_ERR_DHM_MALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + polarssl_free( *buf ); + return( POLARSSL_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int dhm_parse_dhmfile( 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 = dhm_parse_dhm( dhm, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ +#endif /* POLARSSL_ASN1_PARSE_C */ + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/certs.h" + +/* + * Checkup routine + */ +int dhm_self_test( int verbose ) +{ +#if defined(POLARSSL_CERTS_C) + int ret; + dhm_context dhm; + + dhm_init( &dhm ); + + if( verbose != 0 ) + polarssl_printf( " DHM parameter load: " ); + + if( ( ret = dhm_parse_dhm( &dhm, (const unsigned char *) test_dhm_params, + strlen( test_dhm_params ) ) ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n" ); + +exit: + dhm_free( &dhm ); + + return( ret ); +#else + if( verbose != 0 ) + polarssl_printf( " DHM parameter load: skipped\n" ); + + return( 0 ); +#endif /* POLARSSL_CERTS_C */ +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_DHM_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ecdh.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ecdh.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,280 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECDH_C) + +#include "polarssl/ecdh.h" + +#include <string.h> + +/* + * Generate public key: simple wrapper around ecp_gen_keypair + */ +int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); +} + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int ecdh_compute_shared( ecp_group *grp, mpi *z, + const ecp_point *Q, const mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + ecp_point P; + + ecp_point_init( &P ); + + /* + * Make sure Q is a valid pubkey before using it + */ + MPI_CHK( ecp_check_pubkey( grp, Q ) ); + + MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); + + if( ecp_is_zero( &P ) ) + { + ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MPI_CHK( mpi_copy( z, &P.X ) ); + +cleanup: + ecp_point_free( &P ); + + return( ret ); +} + +/* + * Initialize context + */ +void ecdh_init( ecdh_context *ctx ) +{ + memset( ctx, 0, sizeof( ecdh_context ) ); +} + +/* + * Free context + */ +void ecdh_free( ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_group_free( &ctx->grp ); + ecp_point_free( &ctx->Q ); + ecp_point_free( &ctx->Qp ); + ecp_point_free( &ctx->Vi ); + ecp_point_free( &ctx->Vf ); + mpi_free( &ctx->d ); + mpi_free( &ctx->z ); + mpi_free( &ctx->_d ); +} + +/* + * Setup and write the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int ecdh_make_params( 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( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + if( ( ret = ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) + != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = 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 ecdh_read_params( ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ) +{ + int ret; + + if( ( ret = ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) + return( ret ); + + if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) + != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key, + ecdh_side side ) +{ + int ret; + + if( ( ret = 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 == POLARSSL_ECDH_THEIRS ) + return( ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != POLARSSL_ECDH_OURS ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Setup and export the client public value + */ +int ecdh_make_public( 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( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + return ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, + olen, buf, blen ); +} + +/* + * Parse and import the client's public value + */ +int ecdh_read_public( ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret; + const unsigned char *p = buf; + + if( ctx == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Derive and export the shared secret + */ +int ecdh_calc_secret( 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( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mpi_size( &ctx->z ) > blen ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + return mpi_write_binary( &ctx->z, buf, *olen ); +} + + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecdh_self_test( int verbose ) +{ + ((void) verbose ); + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ECDH_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ecdsa.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ecdsa.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,503 @@ +/* + * Elliptic curve DSA + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECDSA_C) + +#include "polarssl/ecdsa.h" +#include "polarssl/asn1write.h" + +#include <string.h> + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +#include "polarssl/hmac_drbg.h" +#endif + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/* + * This a hopefully temporary compatibility function. + * + * Since we can't ensure the caller will pass a valid md_alg before the next + * interface change, try to pick up a decent md by size. + * + * Argument is the minimum size in bytes of the MD output. + */ +static const md_info_t *md_info_by_size( size_t min_size ) +{ + const md_info_t *md_cur, *md_picked = NULL; + const int *md_alg; + + for( md_alg = md_list(); *md_alg != 0; md_alg++ ) + { + if( ( md_cur = md_info_from_type( (md_type_t) *md_alg ) ) == NULL || + (size_t) md_cur->size < min_size || + ( md_picked != NULL && md_cur->size > md_picked->size ) ) + continue; + + md_picked = md_cur; + } + + return( md_picked ); +} +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/* + * 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 ecp_group *grp, 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; + + MPI_CHK( mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MPI_CHK( mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MPI_CHK( 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 ecdsa_sign( ecp_group *grp, mpi *r, mpi *s, + const 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; + ecp_point R; + mpi k, e, t; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + ecp_point_init( &R ); + mpi_init( &k ); mpi_init( &e ); 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 + { + MPI_CHK( ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MPI_CHK( mpi_mod_mpi( r, &R.X, &grp->N ) ); + + if( key_tries++ > 10 ) + { + ret = POLARSSL_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mpi_cmp_int( r, 0 ) == 0 ); + + /* + * Step 5: derive MPI from hashed message + */ + 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; + MPI_CHK( mpi_fill_random( &t, n_size, f_rng, p_rng ) ); + MPI_CHK( mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); + + /* See ecp_gen_keypair() */ + if( ++blind_tries > 30 ) + return( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( &t, 1 ) < 0 || + mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MPI_CHK( mpi_mul_mpi( s, r, d ) ); + MPI_CHK( mpi_add_mpi( &e, &e, s ) ); + MPI_CHK( mpi_mul_mpi( &e, &e, &t ) ); + MPI_CHK( mpi_mul_mpi( &k, &k, &t ) ); + MPI_CHK( mpi_inv_mod( s, &k, &grp->N ) ); + MPI_CHK( mpi_mul_mpi( s, s, &e ) ); + MPI_CHK( mpi_mod_mpi( s, s, &grp->N ) ); + + if( sign_tries++ > 10 ) + { + ret = POLARSSL_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mpi_cmp_int( s, 0 ) == 0 ); + +cleanup: + ecp_point_free( &R ); + mpi_free( &k ); mpi_free( &e ); mpi_free( &t ); + + return( ret ); +} + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s, + const mpi *d, const unsigned char *buf, size_t blen, + md_type_t md_alg ) +{ + int ret; + hmac_drbg_context rng_ctx; + unsigned char data[2 * POLARSSL_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const md_info_t *md_info; + mpi h; + + /* Temporary fallback */ + if( md_alg == POLARSSL_MD_NONE ) + md_info = md_info_by_size( blen ); + else + md_info = md_info_from_type( md_alg ); + + if( md_info == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + mpi_init( &h ); + memset( &rng_ctx, 0, sizeof( hmac_drbg_context ) ); + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MPI_CHK( mpi_write_binary( d, data, grp_len ) ); + MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MPI_CHK( mpi_write_binary( &h, data + grp_len, grp_len ) ); + hmac_drbg_init_buf( &rng_ctx, md_info, data, 2 * grp_len ); + + ret = ecdsa_sign( grp, r, s, d, buf, blen, + hmac_drbg_random, &rng_ctx ); + +cleanup: + hmac_drbg_free( &rng_ctx ); + mpi_free( &h ); + + return( ret ); +} +#endif /* POLARSSL_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 ecdsa_verify( ecp_group *grp, + const unsigned char *buf, size_t blen, + const ecp_point *Q, const mpi *r, const mpi *s) +{ + int ret; + mpi e, s_inv, u1, u2; + ecp_point R, P; + + ecp_point_init( &R ); ecp_point_init( &P ); + mpi_init( &e ); mpi_init( &s_inv ); mpi_init( &u1 ); mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mpi_cmp_int( r, 1 ) < 0 || mpi_cmp_mpi( r, &grp->N ) >= 0 || + mpi_cmp_int( s, 1 ) < 0 || mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = POLARSSL_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Additional precaution: make sure Q is valid + */ + MPI_CHK( ecp_check_pubkey( grp, Q ) ); + + /* + * Step 3: derive MPI from hashed message + */ + MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + MPI_CHK( mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MPI_CHK( mpi_mul_mpi( &u1, &e, &s_inv ) ); + MPI_CHK( mpi_mod_mpi( &u1, &u1, &grp->N ) ); + + MPI_CHK( mpi_mul_mpi( &u2, r, &s_inv ) ); + MPI_CHK( 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 + * ecp_mul() for countermesures. + */ + MPI_CHK( ecp_mul( grp, &R, &u1, &grp->G, NULL, NULL ) ); + MPI_CHK( ecp_mul( grp, &P, &u2, Q, NULL, NULL ) ); + MPI_CHK( ecp_add( grp, &R, &R, &P ) ); + + if( ecp_is_zero( &R ) ) + { + ret = POLARSSL_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MPI_CHK( mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = POLARSSL_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + ecp_point_free( &R ); ecp_point_free( &P ); + mpi_free( &e ); mpi_free( &s_inv ); mpi_free( &u1 ); mpi_free( &u2 ); + + return( ret ); +} + +/* + * RFC 4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + */ +#if POLARSSL_ECP_MAX_BYTES > 124 +#error "POLARSSL_ECP_MAX_BYTES bigger than expected, please fix MAX_SIG_LEN" +#endif +#define MAX_SIG_LEN ( 3 + 2 * ( 3 + POLARSSL_ECP_MAX_BYTES ) ) + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( ecdsa_context *ctx, + unsigned char *sig, size_t *slen ) +{ + int ret; + unsigned char buf[MAX_SIG_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->s ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->r ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &p, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &p, buf, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int ecdsa_write_signature( ecdsa_context *ctx, + 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; + + if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d, + hash, hlen, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + return( ecdsa_signature_to_asn1( ctx, sig, slen ) ); +} + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/* + * Compute and write signature deterministically + */ +int ecdsa_write_signature_det( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + md_type_t md_alg ) +{ + int ret; + + if( ( ret = ecdsa_sign_det( &ctx->grp, &ctx->r, &ctx->s, &ctx->d, + hash, hlen, md_alg ) ) != 0 ) + { + return( ret ); + } + + return( ecdsa_signature_to_asn1( ctx, sig, slen ) ); +} +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/* + * Read and check signature + */ +int ecdsa_read_signature( 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; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret ); + } + + if( p + len != end ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = asn1_get_mpi( &p, end, &ctx->r ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &ctx->s ) ) != 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret ); + + if( ( ret = ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &ctx->r, &ctx->s ) ) != 0 ) + return( ret ); + + if( p != end ) + return( POLARSSL_ERR_ECP_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +/* + * Generate key pair + */ +int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( ecp_use_known_dp( &ctx->grp, gid ) || + ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); +} + +/* + * Set context from an ecp_keypair + */ +int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key ) +{ + int ret; + + if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void ecdsa_init( ecdsa_context *ctx ) +{ + ecp_group_init( &ctx->grp ); + mpi_init( &ctx->d ); + ecp_point_init( &ctx->Q ); + mpi_init( &ctx->r ); + mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void ecdsa_free( ecdsa_context *ctx ) +{ + ecp_group_free( &ctx->grp ); + mpi_free( &ctx->d ); + ecp_point_free( &ctx->Q ); + mpi_free( &ctx->r ); + mpi_free( &ctx->s ); +} + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecdsa_self_test( int verbose ) +{ + ((void) verbose ); + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ECDSA_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ecp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ecp.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,2089 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * 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 + * + * [M255] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-Sébastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25> + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et BÉNÉTEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * <http://eprint.iacr.org/2004/342.pdf> + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECP_C) + +#include "polarssl/ecp.h" + +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#include <stdio.h> +#define polarssl_printf printf +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_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(POLARSSL_ECP_DP_SECP192R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_BP256R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_BP384R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_BP512R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +#define POLARSSL_ECP_SHORT_WEIERSTRASS +#endif + +#if defined(POLARSSL_ECP_DP_M221_ENABLED) || \ + defined(POLARSSL_ECP_DP_M255_ENABLED) || \ + defined(POLARSSL_ECP_DP_M383_ENABLED) || \ + defined(POLARSSL_ECP_DP_M511_ENABLED) +#define POLARSSL_ECP_MONTGOMERY +#endif + +/* + * Curve types: internal for now, might be exposed later + */ +typedef enum +{ + POLARSSL_ECP_TYPE_NONE = 0, + POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + POLARSSL_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. + */ +static const ecp_curve_info ecp_supported_curves[] = +{ +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) + { POLARSSL_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) + { POLARSSL_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) + { POLARSSL_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) + { POLARSSL_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) + { POLARSSL_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + { POLARSSL_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) + { POLARSSL_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) + { POLARSSL_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + { POLARSSL_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + { POLARSSL_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + { POLARSSL_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif + { POLARSSL_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const ecp_curve_info *ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const ecp_group_id *ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = POLARSSL_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id ) +{ + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_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 ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_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 ecp_curve_info *ecp_curve_info_from_name( const char *name ) +{ + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_ECP_DP_NONE; + curve_info++ ) + { + if( strcasecmp( 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 ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( POLARSSL_ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( POLARSSL_ECP_TYPE_MONTGOMERY ); + else + return( POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void ecp_point_init( ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mpi_init( &pt->X ); + mpi_init( &pt->Y ); + mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void ecp_group_init( ecp_group *grp ) +{ + if( grp == NULL ) + return; + + memset( grp, 0, sizeof( ecp_group ) ); +} + +/* + * Initialize (the components of) a key pair + */ +void ecp_keypair_init( ecp_keypair *key ) +{ + if( key == NULL ) + return; + + ecp_group_init( &key->grp ); + mpi_init( &key->d ); + ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void ecp_point_free( ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mpi_free( &( pt->X ) ); + mpi_free( &( pt->Y ) ); + mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void ecp_group_free( ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mpi_free( &grp->P ); + mpi_free( &grp->A ); + mpi_free( &grp->B ); + ecp_point_free( &grp->G ); + mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + ecp_point_free( &grp->T[i] ); + polarssl_free( grp->T ); + } + + polarssl_zeroize( grp, sizeof( ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void ecp_keypair_free( ecp_keypair *key ) +{ + if( key == NULL ) + return; + + ecp_group_free( &key->grp ); + mpi_free( &key->d ); + ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int ecp_copy( ecp_point *P, const ecp_point *Q ) +{ + int ret; + + MPI_CHK( mpi_copy( &P->X, &Q->X ) ); + MPI_CHK( mpi_copy( &P->Y, &Q->Y ) ); + MPI_CHK( mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int ecp_group_copy( ecp_group *dst, const ecp_group *src ) +{ + return ecp_use_known_dp( dst, src->id ); +} + +/* + * Set point to zero + */ +int ecp_set_zero( ecp_point *pt ) +{ + int ret; + + MPI_CHK( mpi_lset( &pt->X , 1 ) ); + MPI_CHK( mpi_lset( &pt->Y , 1 ) ); + MPI_CHK( mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int ecp_is_zero( ecp_point *pt ) +{ + return( mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int ecp_point_read_string( ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret; + + MPI_CHK( mpi_read_string( &P->X, radix, x ) ); + MPI_CHK( mpi_read_string( &P->Y, radix, y ) ); + MPI_CHK( mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3) + */ +int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = 0; + size_t plen; + + if( format != POLARSSL_ECP_PF_UNCOMPRESSED && + format != POLARSSL_ECP_PF_COMPRESSED ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Common case: P == 0 + */ + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mpi_size( &grp->P ); + + if( format == POLARSSL_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); + MPI_CHK( mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == POLARSSL_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mpi_get_bit( &P->Y, 0 ); + MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); + } + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int ecp_point_read_binary( const ecp_group *grp, ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret; + size_t plen; + + if( ilen < 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( ecp_set_zero( pt ) ); + else + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + } + + plen = mpi_size( &grp->P ); + + if( buf[0] != 0x04 ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + MPI_CHK( mpi_read_binary( &pt->X, buf + 1, plen ) ); + MPI_CHK( mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); + MPI_CHK( 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 ecp_tls_read_point( const ecp_group *grp, 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( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return 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 ecp_tls_write_point( const ecp_group *grp, const 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( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = 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 ); +} + +/* + * Import an ECP group from ASCII strings, case A == -3 + */ +int ecp_group_read_string( ecp_group *grp, int radix, + const char *p, const char *b, + const char *gx, const char *gy, const char *n) +{ + int ret; + + MPI_CHK( mpi_read_string( &grp->P, radix, p ) ); + MPI_CHK( mpi_read_string( &grp->B, radix, b ) ); + MPI_CHK( ecp_point_read_string( &grp->G, radix, gx, gy ) ); + MPI_CHK( mpi_read_string( &grp->N, radix, n ) ); + + grp->pbits = mpi_msb( &grp->P ); + grp->nbits = mpi_msb( &grp->N ); + +cleanup: + if( ret != 0 ) + ecp_group_free( grp ); + + return( ret ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const ecp_curve_info *curve_info; + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != POLARSSL_ECP_TLS_NAMED_CURVE ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + return ecp_use_known_dp( grp, curve_info->grp_id ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int ecp_tls_write_group( const ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const ecp_curve_info *curve_info; + + if( ( curve_info = ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = POLARSSL_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 mpi_mod_mpi. + * See the documentation of struct ecp_group. + * + * This function is in the critial loop for ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mpi *N, const ecp_group *grp ) +{ + int ret; + + if( grp->modp == NULL ) + return( 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 && mpi_cmp_int( N, 0 ) != 0 ) || + mpi_msb( N ) > 2 * grp->pbits ) + { + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + } + + MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mpi_cmp_int( N, 0 ) != 0 ) + MPI_CHK( mpi_add_mpi( N, N, &grp->P ) ); + + while( mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MPI_CHK( 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 + * 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 mpi mod p in-place, general case, to use after mpi_mul_mpi + */ +#if defined(POLARSSL_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) do { MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ + while( 0 ) + +/* + * Reduce a mpi mod p in-place, to use after 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 && mpi_cmp_int( &N, 0 ) != 0 ) \ + MPI_CHK( mpi_add_mpi( &N, &N, &grp->P ) ) + +/* + * Reduce a mpi mod p in-place, to use after mpi_add_mpi and 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( mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ + MPI_CHK( mpi_sub_abs( &N, &N, &grp->P ) ) + +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) +/* + * 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 ecp_group *grp, ecp_point *pt ) +{ + int ret; + mpi Zi, ZZi; + + if( mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + + mpi_init( &Zi ); mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MPI_CHK( mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MPI_CHK( mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); + + /* + * Y = Y / Z^3 mod p + */ + MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); + MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); + + /* + * Z = 1 + */ + MPI_CHK( mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mpi_free( &Zi ); 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 ecp_group *grp, + ecp_point *T[], size_t t_len ) +{ + int ret; + size_t i; + mpi *c, u, Zi, ZZi; + + if( t_len < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + + if( ( c = polarssl_malloc( t_len * sizeof( mpi ) ) ) == NULL ) + return( POLARSSL_ERR_ECP_MALLOC_FAILED ); + + mpi_init( &u ); mpi_init( &Zi ); mpi_init( &ZZi ); + for( i = 0; i < t_len; i++ ) + mpi_init( &c[i] ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MPI_CHK( mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < t_len; i++ ) + { + MPI_CHK( mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); + MOD_MUL( c[i] ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MPI_CHK( 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 ) { + MPI_CHK( mpi_copy( &Zi, &u ) ); + } + else + { + MPI_CHK( mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); + MPI_CHK( mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); + } + + /* + * proceed as in normalize() + */ + MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MPI_CHK( mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); + MPI_CHK( mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); + MPI_CHK( 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. + */ + MPI_CHK( mpi_shrink( &T[i]->X, grp->P.n ) ); + MPI_CHK( mpi_shrink( &T[i]->Y, grp->P.n ) ); + mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mpi_free( &u ); mpi_free( &Zi ); mpi_free( &ZZi ); + for( i = 0; i < t_len; i++ ) + mpi_free( &c[i] ); + polarssl_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 ecp_group *grp, + ecp_point *Q, + unsigned char inv ) +{ + int ret; + unsigned char nonzero; + mpi mQY; + + mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MPI_CHK( mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mpi_cmp_int( &Q->Y, 0 ) != 0; + MPI_CHK( mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + 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 ecp_group *grp, ecp_point *R, + const ecp_point *P ) +{ + int ret; + mpi M, S, T, U; + +#if defined(POLARSSL_SELF_TEST) + dbl_count++; +#endif + + mpi_init( &M ); mpi_init( &S ); mpi_init( &T ); mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MPI_CHK( mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MPI_CHK( mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); + MPI_CHK( mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); + MPI_CHK( mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); + MPI_CHK( mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MPI_CHK( mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); + MPI_CHK( mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MPI_CHK( mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MPI_CHK( mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); + MPI_CHK( mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); + MPI_CHK( mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); + } + } + + /* S = 4.X.Y^2 */ + MPI_CHK( mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); + MPI_CHK( mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); + MPI_CHK( mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); + MPI_CHK( mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); + + /* U = 8.Y^4 */ + MPI_CHK( mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); + MPI_CHK( mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + /* T = M^2 - 2.S */ + MPI_CHK( mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); + MPI_CHK( mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + MPI_CHK( mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + + /* S = M(S - T) - U */ + MPI_CHK( mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); + MPI_CHK( mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); + MPI_CHK( mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); + + /* U = 2.Y.Z */ + MPI_CHK( mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); + MPI_CHK( mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + MPI_CHK( mpi_copy( &R->X, &T ) ); + MPI_CHK( mpi_copy( &R->Y, &S ) ); + MPI_CHK( mpi_copy( &R->Z, &U ) ); + +cleanup: + mpi_free( &M ); mpi_free( &S ); mpi_free( &T ); 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 ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret; + mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(POLARSSL_SELF_TEST) + add_count++; +#endif + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 ); + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + + MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); + MPI_CHK( mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); + MPI_CHK( mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); + MPI_CHK( mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); + + /* Special cases (2) and (3) */ + if( mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = ecp_set_zero( R ); + goto cleanup; + } + } + + MPI_CHK( mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); + MPI_CHK( mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); + MPI_CHK( mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); + MPI_CHK( mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); + MPI_CHK( mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); + MPI_CHK( mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); + + MPI_CHK( mpi_copy( &R->X, &X ) ); + MPI_CHK( mpi_copy( &R->Y, &Y ) ); + MPI_CHK( mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 ); mpi_free( &T4 ); + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); + + return( ret ); +} + +/* + * Addition: R = P + Q, result's coordinates normalized + */ +int ecp_add( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret; + + if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + MPI_CHK( ecp_add_mixed( grp, R, P, Q ) ); + MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + return( ret ); +} + +/* + * Subtraction: R = P - Q, result's coordinates normalized + */ +int ecp_sub( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret; + ecp_point mQ; + + ecp_point_init( &mQ ); + + if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + /* mQ = - Q */ + MPI_CHK( ecp_copy( &mQ, Q ) ); + if( mpi_cmp_int( &mQ.Y, 0 ) != 0 ) + MPI_CHK( mpi_sub_mpi( &mQ.Y, &grp->P, &mQ.Y ) ); + + MPI_CHK( ecp_add_mixed( grp, R, P, &mQ ) ); + MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + ecp_point_free( &mQ ); + + 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 ecp_group *grp, ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mpi l, ll; + size_t p_size = ( grp->pbits + 7 ) / 8; + int count = 0; + + mpi_init( &l ); mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + mpi_fill_random( &l, p_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MPI_CHK( mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); + + /* X = l^2 * X */ + MPI_CHK( mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); + MPI_CHK( mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); + + /* Y = l^3 * Y */ + MPI_CHK( mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); + MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); + +cleanup: + mpi_free( &l ); mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if POLARSSL_ECP_WINDOW_SIZE < 2 || POLARSSL_ECP_WINDOW_SIZE > 7 +#error "POLARSSL_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( POLARSSL_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( POLARSSL_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 POLARSSL_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 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] |= 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 ecp_group *grp, + ecp_point T[], const ecp_point *P, + unsigned char w, size_t d ) +{ + int ret; + unsigned char i, k; + size_t j; + 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) + */ + MPI_CHK( ecp_copy( &T[0], P ) ); + + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + cur = T + i; + MPI_CHK( ecp_copy( cur, T + ( i >> 1 ) ) ); + for( j = 0; j < d; j++ ) + MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + + TT[k++] = cur; + } + + 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-- ) + { + MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + TT[k++] = &T[i + j]; + } + } + + 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 ecp_group *grp, ecp_point *R, + const 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++ ) + { + MPI_CHK( mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MPI_CHK( mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + 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 ecp_group *grp, ecp_point *R, + const 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; + ecp_point Txi; + size_t i; + + ecp_point_init( &Txi ); + + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MPI_CHK( mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + + while( i-- != 0 ) + { + MPI_CHK( ecp_double_jac( grp, R, R ) ); + MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + ecp_point_free( &Txi ); + + return( ret ); +} + +/* + * Multiplication using the comb method, + * for curves in short Weierstrass form + */ +static int ecp_mul_comb( ecp_group *grp, ecp_point *R, + const mpi *m, const 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]; + ecp_point *T; + mpi M, mm; + + mpi_init( &M ); + mpi_init( &mm ); + + /* we need N to be odd to trnaform m in an odd number, check now */ + if( mpi_get_bit( &grp->N, 0 ) != 1 ) + return( POLARSSL_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 POLARSSL_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + 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 > POLARSSL_ECP_WINDOW_SIZE ) + w = POLARSSL_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 = polarssl_malloc( pre_len * sizeof( ecp_point ) ); + if( T == NULL ) + { + ret = POLARSSL_ERR_ECP_MALLOC_FAILED; + goto cleanup; + } + + for( i = 0; i < pre_len; i++ ) + ecp_point_init( &T[i] ); + + 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 = ( mpi_get_bit( m, 0 ) == 1 ); + MPI_CHK( mpi_copy( &M, m ) ); + MPI_CHK( mpi_sub_mpi( &mm, &grp->N, m ) ); + MPI_CHK( mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + + /* + * Go for comb multiplication, R = M * P + */ + ecp_comb_fixed( k, d, w, &M ); + 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 + */ + MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + + if( T != NULL && ! p_eq_g ) + { + for( i = 0; i < pre_len; i++ ) + ecp_point_free( &T[i] ); + polarssl_free( T ); + } + + mpi_free( &M ); + mpi_free( &mm ); + + if( ret != 0 ) + ecp_point_free( R ); + + return( ret ); +} + +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + +#if defined(POLARSSL_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 ecp_group *grp, ecp_point *P ) +{ + int ret; + + MPI_CHK( mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); + MPI_CHK( 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 ecp_group *grp, ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mpi l; + size_t p_size = ( grp->pbits + 7 ) / 8; + int count = 0; + + mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + mpi_fill_random( &l, p_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( &l, 1 ) <= 0 ); + + MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); + MPI_CHK( mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); + +cleanup: + 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 ecp_group *grp, + ecp_point *R, ecp_point *S, + const ecp_point *P, const ecp_point *Q, + const mpi *d ) +{ + int ret; + mpi A, AA, B, BB, E, C, D, DA, CB; + + mpi_init( &A ); mpi_init( &AA ); mpi_init( &B ); + mpi_init( &BB ); mpi_init( &E ); mpi_init( &C ); + mpi_init( &D ); mpi_init( &DA ); mpi_init( &CB ); + + MPI_CHK( mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); + MPI_CHK( mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); + MPI_CHK( mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); + MPI_CHK( mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); + MPI_CHK( mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); + MPI_CHK( mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); + MPI_CHK( mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); + MPI_CHK( mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); + MPI_CHK( mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); + MPI_CHK( mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); + MPI_CHK( mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); + MPI_CHK( mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); + MPI_CHK( mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); + MPI_CHK( mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); + MPI_CHK( mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); + MPI_CHK( mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); + MPI_CHK( mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); + MPI_CHK( mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); + +cleanup: + mpi_free( &A ); mpi_free( &AA ); mpi_free( &B ); + mpi_free( &BB ); mpi_free( &E ); mpi_free( &C ); + mpi_free( &D ); mpi_free( &DA ); mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i; + unsigned char b; + ecp_point RP; + mpi PX; + + ecp_point_init( &RP ); mpi_init( &PX ); + + /* Save PX and read from P before writing to R, in case P == R */ + MPI_CHK( mpi_copy( &PX, &P->X ) ); + MPI_CHK( ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MPI_CHK( mpi_lset( &R->X, 1 ) ); + MPI_CHK( mpi_lset( &R->Z, 0 ) ); + 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 ) + MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mpi_msb( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = 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 + */ + MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: + ecp_point_free( &RP ); mpi_free( &PX ); + + return( ret ); +} + +#endif /* POLARSSL_ECP_MONTGOMERY */ + +/* + * Multiplication R = m * P + */ +int ecp_mul( ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + /* Common sanity checks */ + if( mpi_cmp_int( &P->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecp_check_privkey( grp, m ) ) != 0 || + ( ret = ecp_check_pubkey( grp, P ) ) != 0 ) + return( ret ); + +#if defined(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng ) ); +#endif + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); +} + +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) +/* + * 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 ecp_group *grp, const ecp_point *pt ) +{ + int ret; + mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mpi_cmp_int( &pt->X, 0 ) < 0 || + mpi_cmp_int( &pt->Y, 0 ) < 0 || + mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + + mpi_init( &YY ); mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MPI_CHK( mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MPI_CHK( mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MPI_CHK( mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); + } + + MPI_CHK( mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = POLARSSL_ERR_ECP_INVALID_KEY; + +cleanup: + + mpi_free( &YY ); mpi_free( &RHS ); + + return( ret ); +} +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + + +#if defined(POLARSSL_ECP_MONTGOMERY) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const ecp_group *grp, const ecp_point *pt ) +{ + /* [M255 p. 5] Just check X is the correct number of bytes */ + if( mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* POLARSSL_ECP_MONTGOMERY */ + +/* + * Check that a point is valid as a public key + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ) +{ + /* Must use affine coordinates */ + if( mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + +#if defined(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mpi is valid as a private key + */ +int ecp_check_privkey( const ecp_group *grp, const mpi *d ) +{ +#if defined(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + { + /* see [M255] page 5 */ + if( mpi_get_bit( d, 0 ) != 0 || + mpi_get_bit( d, 1 ) != 0 || + mpi_get_bit( d, 2 ) != 0 || + mpi_msb( d ) - 1 != grp->nbits ) /* mpi_msb is one-based! */ + return( POLARSSL_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* POLARSSL_ECP_MONTGOMERY */ +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mpi_cmp_int( d, 1 ) < 0 || + mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair + */ +int ecp_gen_keypair( ecp_group *grp, mpi *d, 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(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + MPI_CHK( mpi_fill_random( d, n_size, f_rng, p_rng ) ); + + /* Make sure the most significant bit is nbits */ + b = mpi_msb( d ) - 1; /* mpi_msb is one-based */ + if( b > grp->nbits ) + MPI_CHK( mpi_shift_r( d, b - grp->nbits ) ); + else + MPI_CHK( mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last three bits are unset */ + MPI_CHK( mpi_set_bit( d, 0, 0 ) ); + MPI_CHK( mpi_set_bit( d, 1, 0 ) ); + MPI_CHK( mpi_set_bit( d, 2, 0 ) ); + } + else +#endif /* POLARSSL_ECP_MONTGOMERY */ +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + unsigned char rnd[POLARSSL_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 + { + MPI_CHK( f_rng( p_rng, rnd, n_size ) ); + MPI_CHK( mpi_read_binary( d, rnd, n_size ) ); + MPI_CHK( 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( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( d, 1 ) < 0 || + mpi_cmp_mpi( d, &grp->N ) >= 0 ); + } + else +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + +cleanup: + if( ret != 0 ) + return( ret ); + + return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +/* + * Check a public-private key pair + */ +int ecp_check_pub_priv( const ecp_keypair *pub, const ecp_keypair *prv ) +{ + int ret; + ecp_point Q; + ecp_group grp; + + if( pub->grp.id == POLARSSL_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + } + + ecp_point_init( &Q ); + ecp_group_init( &grp ); + + /* ecp_mul() needs a non-const group... */ + ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MPI_CHK( ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + ecp_point_free( &Q ); + ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecp_self_test( int verbose ) +{ + int ret; + size_t i; + ecp_group grp; + ecp_point R, P; + 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... */ + }; + + ecp_group_init( &grp ); + ecp_point_init( &R ); + ecp_point_init( &P ); + mpi_init( &m ); + + /* Use secp192r1 if available, or any available curve */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + MPI_CHK( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_SECP192R1 ) ); +#else + MPI_CHK( ecp_use_known_dp( &grp, ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + polarssl_printf( " ECP test #1 (constant op_count, base point G): " ); + + /* Do a dummy multiplication first to trigger precomputation */ + MPI_CHK( mpi_lset( &m, 2 ) ); + MPI_CHK( ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) ); + MPI_CHK( 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; + + MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) ); + MPI_CHK( 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 ) + polarssl_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_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; + MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) ); + MPI_CHK( 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; + + MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) ); + MPI_CHK( 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 ) + polarssl_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + +cleanup: + + if( ret < 0 && verbose != 0 ) + polarssl_printf( "Unexpected error, return code = %08X\n", ret ); + + ecp_group_free( &grp ); + ecp_point_free( &R ); + ecp_point_free( &P ); + mpi_free( &m ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ECP_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ecp_curves.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ecp_curves.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1380 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECP_C) + +#include "polarssl/ecp.h" + +#include <string.h> + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +/* + * Conversion macros for embedded constants: + * build lists of t_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(POLARSSL_HAVE_INT8) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + a, b, c, d, e, f, g, h + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + a, b, c, d + +#define BYTES_TO_T_UINT_2( a, b ) \ + a, b + +#elif defined(POLARSSL_HAVE_INT16) + +#define BYTES_TO_T_UINT_2( a, b ) \ + ( (t_uint) a << 0 ) | \ + ( (t_uint) b << 8 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_2( a, b ), \ + BYTES_TO_T_UINT_2( c, d ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_2( a, b ), \ + BYTES_TO_T_UINT_2( c, d ), \ + BYTES_TO_T_UINT_2( e, f ), \ + BYTES_TO_T_UINT_2( g, h ) + +#elif defined(POLARSSL_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (t_uint) a << 0 ) | \ + ( (t_uint) b << 8 ) | \ + ( (t_uint) c << 16 ) | \ + ( (t_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 ) \ + ( (t_uint) a << 0 ) | \ + ( (t_uint) b << 8 ) | \ + ( (t_uint) c << 16 ) | \ + ( (t_uint) d << 24 ) | \ + ( (t_uint) e << 32 ) | \ + ( (t_uint) f << 40 ) | \ + ( (t_uint) g << 48 ) | \ + ( (t_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 t_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +static const t_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 t_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const t_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +static const t_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 t_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const t_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +static const t_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 t_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const t_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const t_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 t_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 t_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 /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) +static const t_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 t_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 t_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 t_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 t_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 t_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 /* POLARSSL_ECP_DP_BP512R1_ENABLED */ + +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof t_uint) + */ +static inline void ecp_mpi_load( mpi *X, const t_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( t_uint ); + X->p = (t_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mpi *X ) +{ + static t_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( ecp_group *grp, + const t_uint *p, size_t plen, + const t_uint *a, size_t alen, + const t_uint *b, size_t blen, + const t_uint *gx, size_t gxlen, + const t_uint *gy, size_t gylen, + const t_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 = mpi_msb( &grp->P ); + grp->nbits = mpi_msb( &grp->N ); + + grp->h = 1; + + return( 0 ); +} + +#if defined(POLARSSL_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* POLARSSL_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(POLARSSL_ECP_DP_M255_ENABLED) +static int ecp_mod_p255( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( 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(POLARSSL_ECP_DP_M255_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( ecp_group *grp ) +{ + int ret; + + /* Actually ( A + 2 ) / 4 */ + MPI_CHK( mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MPI_CHK( mpi_lset( &grp->P, 1 ) ); + MPI_CHK( mpi_shift_l( &grp->P, 255 ) ); + MPI_CHK( mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mpi_msb( &grp->P ); + + /* Y intentionaly not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MPI_CHK( mpi_lset( &grp->G.X, 9 ) ); + MPI_CHK( mpi_lset( &grp->G.Z, 1 ) ); + mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + ecp_group_free( grp ); + + return( ret ); +} +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) +{ + ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + case POLARSSL_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) + case POLARSSL_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) + case POLARSSL_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) + case POLARSSL_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) + case POLARSSL_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + case POLARSSL_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + case POLARSSL_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + case POLARSSL_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) + case POLARSSL_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) + case POLARSSL_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) + case POLARSSL_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_M255_ENABLED) + case POLARSSL_ECP_DP_M255: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ + + default: + ecp_group_free( grp ); + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(POLARSSL_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(POLARSSL_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 t_uint, we can + * use a t_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( t_uint *dst, t_uint *src, t_uint *carry ) +{ + unsigned char i; + t_uint c = 0; + for( i = 0; i < 8 / sizeof( t_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( t_uint *dst, t_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( t_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( mpi *N ) +{ + int ret; + t_uint c = 0; + t_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MPI_CHK( 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 /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \ + defined(POLARSSL_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(POLARSSL_HAVE_INT8) /* 8 bit */ + +#define MAX32 N->n / 4 +#define A( j ) (uint32_t)( N->p[4*j+0] ) | \ + ( N->p[4*j+1] << 8 ) | \ + ( N->p[4*j+2] << 16 ) | \ + ( N->p[4*j+3] << 24 ) +#define STORE32 N->p[4*i+0] = (t_uint)( cur ); \ + N->p[4*i+1] = (t_uint)( cur >> 8 ); \ + N->p[4*i+2] = (t_uint)( cur >> 16 ); \ + N->p[4*i+3] = (t_uint)( cur >> 24 ); + +#elif defined(POLARSSL_HAVE_INT16) /* 16 bit */ + +#define MAX32 N->n / 2 +#define A( j ) (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 ) +#define STORE32 N->p[2*i+0] = (t_uint)( cur ); \ + N->p[2*i+1] = (t_uint)( cur >> 16 ); + +#elif defined(POLARSSL_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] |= ((t_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (t_uint) cur; \ + } + +#endif /* sizeof( t_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; \ + mpi C; \ + t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = b / 8 / sizeof( t_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( t_uint ) ); \ + \ + MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_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( mpi *N, signed char c, mpi *C, size_t bits ) +{ + int ret; + + /* C = - c * 2^(bits + 32) */ +#if !defined(POLARSSL_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((t_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (t_uint) -c; + + /* N = - ( C - N ) */ + MPI_CHK( mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( 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 /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( 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 /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( 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 /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED || + POLARSSL_ECP_DP_SECP256R1_ENABLED || + POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +#if defined(POLARSSL_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 t_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( t_uint ) + 1 ) + +/* Bits to keep in the most significant t_uint */ +#if defined(POLARSSL_HAVE_INT8) +#define P521_MASK 0x01 +#else +#define P521_MASK 0x01FF +#endif + +/* + * 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( mpi *N ) +{ + int ret; + size_t i; + mpi M; + t_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when t_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( t_uint ) ); + MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_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 */ + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ + +#endif /* POLARSSL_ECP_NIST_OPTIM */ + +#if defined(POLARSSL_ECP_DP_M255_ENABLED) + +/* Size of p255 in terms of t_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( t_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( mpi *N ) +{ + int ret; + size_t i; + mpi M; + t_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( t_uint ) ); + MPI_CHK( mpi_shift_r( &M, 255 % ( 8 * sizeof( t_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MPI_CHK( mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MPI_CHK( mpi_mul_int( &M, &M, 19 ) ); + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) || \ + defined(POLARSSL_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( t_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( t_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mpi *N, t_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, t_uint mask ) +{ + int ret; + size_t i; + mpi M, R; + t_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( t_uint ) ); + if( shift != 0 ) + MPI_CHK( 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 */ + MPI_CHK( mpi_mul_mpi( &M, &M, &R ) ); + MPI_CHK( 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( t_uint ) ); + if( shift != 0 ) + MPI_CHK( 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 */ + MPI_CHK( mpi_mul_mpi( &M, &M, &R ) ); + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED) || + POLARSSL_ECP_DP_SECP224K1_ENABLED) || + POLARSSL_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(POLARSSL_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( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +} +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + +#if defined(POLARSSL_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( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(POLARSSL_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + +#if defined(POLARSSL_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( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +} +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + +#endif /* POLARSSL_ECP_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/entropy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/entropy.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,478 @@ +/* + * Entropy accumulator implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ENTROPY_C) + +#include "polarssl/entropy.h" +#include "polarssl/entropy_poll.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +#if defined(POLARSSL_HAVEGE_C) +#include "polarssl/havege.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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 entropy_init( entropy_context *ctx ) +{ + memset( ctx, 0, sizeof(entropy_context) ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &ctx->mutex ); +#endif + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_starts( &ctx->accumulator, 0 ); +#else + sha256_starts( &ctx->accumulator, 0 ); +#endif +#if defined(POLARSSL_HAVEGE_C) + havege_init( &ctx->havege_data ); +#endif + +#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) + entropy_add_source( ctx, platform_entropy_poll, NULL, + ENTROPY_MIN_PLATFORM ); +#endif +#if defined(POLARSSL_TIMING_C) + entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); +#endif +#if defined(POLARSSL_HAVEGE_C) + entropy_add_source( ctx, havege_poll, &ctx->havege_data, + ENTROPY_MIN_HAVEGE ); +#endif +#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void entropy_free( entropy_context *ctx ) +{ +#if defined(POLARSSL_HAVEGE_C) + havege_free( &ctx->havege_data ); +#endif +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &ctx->mutex ); +#endif + polarssl_zeroize( ctx, sizeof( entropy_context ) ); +} + +int entropy_add_source( entropy_context *ctx, + f_source_ptr f_source, void *p_source, + size_t threshold ) +{ + int index, ret = 0; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + index = ctx->source_count; + if( index >= ENTROPY_MAX_SOURCES ) + { + ret = POLARSSL_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_count++; + +exit: +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + + if( use_len > ENTROPY_BLOCK_SIZE ) + { +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512( data, len, tmp, 0 ); +#else + sha256( data, len, tmp, 0 ); +#endif + p = tmp; + use_len = ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_update( &ctx->accumulator, header, 2 ); + sha512_update( &ctx->accumulator, p, use_len ); +#else + sha256_update( &ctx->accumulator, header, 2 ); + sha256_update( &ctx->accumulator, p, use_len ); +#endif + + return( 0 ); +} + +int entropy_update_manual( entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( entropy_context *ctx ) +{ + int ret, i; + unsigned char buf[ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, 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; + } + } + + return( 0 ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int entropy_gather( entropy_context *ctx ) +{ + int ret; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, reached; + entropy_context *ctx = (entropy_context *) data; + unsigned char buf[ENTROPY_BLOCK_SIZE]; + + if( len > ENTROPY_BLOCK_SIZE ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + reached = 0; + + for( i = 0; i < ctx->source_count; i++ ) + if( ctx->source[i].size >= ctx->source[i].threshold ) + reached++; + } + while( reached != ctx->source_count ); + + memset( buf, 0, ENTROPY_BLOCK_SIZE ); + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_finish( &ctx->accumulator, buf ); + + /* + * Reset accumulator and counters and recycle existing entropy + */ + memset( &ctx->accumulator, 0, sizeof( sha512_context ) ); + sha512_starts( &ctx->accumulator, 0 ); + sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); + + /* + * Perform second SHA-512 on entropy + */ + sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); +#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ + sha256_finish( &ctx->accumulator, buf ); + + /* + * Reset accumulator and counters and recycle existing entropy + */ + memset( &ctx->accumulator, 0, sizeof( sha256_context ) ); + sha256_starts( &ctx->accumulator, 0 ); + sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); + + /* + * Perform second SHA-256 on entropy + */ + sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); +#endif /* POLARSSL_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(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(POLARSSL_FS_IO) +int entropy_write_seed_file( entropy_context *ctx, const char *path ) +{ + int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ENTROPY_BLOCK_SIZE]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); + + if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE ) + { + ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int entropy_update_seed_file( entropy_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > ENTROPY_MAX_SEED_SIZE ) + n = ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); + } + + fclose( f ); + + entropy_update_manual( ctx, buf, n ); + + return( entropy_write_seed_file( ctx, path ) ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_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 entropy_self_test( int verbose ) +{ + int ret = 0; + entropy_context ctx; + unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; + + if( verbose != 0 ) + polarssl_printf( " ENTROPY test: " ); + + entropy_init( &ctx ); + + ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that 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 = 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: + entropy_free( &ctx ); + + if( verbose != 0 ) + { + if( ret != 0 ) + polarssl_printf( "failed\n" ); + else + polarssl_printf( "passed\n" ); + + polarssl_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ENTROPY_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/entropy_poll.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/entropy_poll.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,211 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ENTROPY_C) + +#include "polarssl/entropy.h" +#include "polarssl/entropy_poll.h" + +#if defined(POLARSSL_TIMING_C) +#include <string.h> +#include "polarssl/timing.h" +#endif +#if defined(POLARSSL_HAVEGE_C) +#include "polarssl/havege.h" +#endif + +#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include <windows.h> +#include <wincrypt.h> + +int 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( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + return( POLARSSL_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 <linux/version.h> +#include <unistd.h> +#include <sys/syscall.h> +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} + +#include <sys/utsname.h> +/* 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 <stdio.h> + +int platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t ret; + ((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( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); + } +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + ret = fread( output, 1, len, file ); + if( ret != len ) + { + fclose( file ); + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !POLARSSL_NO_PLATFORM_ENTROPY */ + +#if defined(POLARSSL_TIMING_C) +int hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = 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 /* POLARSSL_TIMING_C */ + +#if defined(POLARSSL_HAVEGE_C) +int havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + havege_state *hs = (havege_state *) data; + *olen = 0; + + if( havege_random( hs, output, len ) != 0 ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* POLARSSL_HAVEGE_C */ + +#endif /* POLARSSL_ENTROPY_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/error.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/error.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,775 @@ +/* + * Error message information + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ERROR_C) || defined(POLARSSL_ERROR_STRERROR_DUMMY) +#include "polarssl/error.h" +#include <string.h> +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_snprintf snprintf +#endif + +#if defined(POLARSSL_ERROR_C) + +#include <stdio.h> + +#if defined(POLARSSL_AES_C) +#include "polarssl/aes.h" +#endif + +#if defined(POLARSSL_BASE64_C) +#include "polarssl/base64.h" +#endif + +#if defined(POLARSSL_BIGNUM_C) +#include "polarssl/bignum.h" +#endif + +#if defined(POLARSSL_BLOWFISH_C) +#include "polarssl/blowfish.h" +#endif + +#if defined(POLARSSL_CAMELLIA_C) +#include "polarssl/camellia.h" +#endif + +#if defined(POLARSSL_CCM_C) +#include "polarssl/ccm.h" +#endif + +#if defined(POLARSSL_CIPHER_C) +#include "polarssl/cipher.h" +#endif + +#if defined(POLARSSL_CTR_DRBG_C) +#include "polarssl/ctr_drbg.h" +#endif + +#if defined(POLARSSL_DES_C) +#include "polarssl/des.h" +#endif + +#if defined(POLARSSL_DHM_C) +#include "polarssl/dhm.h" +#endif + +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + +#if defined(POLARSSL_ENTROPY_C) +#include "polarssl/entropy.h" +#endif + +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + +#if defined(POLARSSL_HMAC_DRBG_C) +#include "polarssl/hmac_drbg.h" +#endif + +#if defined(POLARSSL_MD_C) +#include "polarssl/md.h" +#endif + +#if defined(POLARSSL_MD2_C) +#include "polarssl/md2.h" +#endif + +#if defined(POLARSSL_MD4_C) +#include "polarssl/md4.h" +#endif + +#if defined(POLARSSL_MD5_C) +#include "polarssl/md5.h" +#endif + +#if defined(POLARSSL_NET_C) +#include "polarssl/net.h" +#endif + +#if defined(POLARSSL_OID_C) +#include "polarssl/oid.h" +#endif + +#if defined(POLARSSL_PADLOCK_C) +#include "polarssl/padlock.h" +#endif + +#if defined(POLARSSL_PBKDF2_C) +#include "polarssl/pbkdf2.h" +#endif + +#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PK_C) +#include "polarssl/pk.h" +#endif + +#if defined(POLARSSL_PKCS12_C) +#include "polarssl/pkcs12.h" +#endif + +#if defined(POLARSSL_PKCS5_C) +#include "polarssl/pkcs5.h" +#endif + +#if defined(POLARSSL_RIPEMD160_C) +#include "polarssl/ripemd160.h" +#endif + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif + +#if defined(POLARSSL_SHA1_C) +#include "polarssl/sha1.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#include "polarssl/sha256.h" +#endif + +#if defined(POLARSSL_SHA512_C) +#include "polarssl/sha512.h" +#endif + +#if defined(POLARSSL_SSL_TLS_C) +#include "polarssl/ssl.h" +#endif + +#if defined(POLARSSL_THREADING_C) +#include "polarssl/threading.h" +#endif + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "polarssl/x509.h" +#endif + +#if defined(POLARSSL_XTEA_C) +#include "polarssl/xtea.h" +#endif + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#define snprintf _snprintf +#endif + +void polarssl_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + /* Reduce buflen to make sure MSVC _snprintf() ends with \0 as well */ + buflen -= 1; + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +#if defined(POLARSSL_CIPHER_C) + if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) ) + polarssl_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) + polarssl_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_AUTH_FAILED) ) + polarssl_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); +#endif /* POLARSSL_CIPHER_C */ + +#if defined(POLARSSL_DHM_C) + if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "DHM - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) ) + polarssl_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) ) + polarssl_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) ) + polarssl_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) ) + polarssl_snprintf( buf, buflen, "DHM - Making of the public value failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) ) + polarssl_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_INVALID_FORMAT) ) + polarssl_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); + if( use_ret == -(POLARSSL_ERR_DHM_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "DHM - Read/write of file failed" ); +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_ECP_C) + if( use_ret == -(POLARSSL_ERR_ECP_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_ECP_BUFFER_TOO_SMALL) ) + polarssl_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); + if( use_ret == -(POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "ECP - Requested curve not available" ); + if( use_ret == -(POLARSSL_ERR_ECP_VERIFY_FAILED) ) + polarssl_snprintf( buf, buflen, "ECP - The signature is not valid" ); + if( use_ret == -(POLARSSL_ERR_ECP_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "ECP - Memory allocation failed" ); + if( use_ret == -(POLARSSL_ERR_ECP_RANDOM_FAILED) ) + polarssl_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); + if( use_ret == -(POLARSSL_ERR_ECP_INVALID_KEY) ) + polarssl_snprintf( buf, buflen, "ECP - Invalid private or public key" ); + if( use_ret == -(POLARSSL_ERR_ECP_SIG_LEN_MISMATCH) ) + polarssl_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_MD_C) + if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "MD - The selected feature is not available" ); + if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "MD - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "MD - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); +#endif /* POLARSSL_MD_C */ + +#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C) + if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) + polarssl_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); + if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) ) + polarssl_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); + if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) ) + polarssl_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); + if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) ) + polarssl_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); + if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) ) + polarssl_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); + if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) ) + polarssl_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); + if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + if( use_ret == -(POLARSSL_ERR_PEM_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); +#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */ + +#if defined(POLARSSL_PK_C) + if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "PK - Memory alloation failed" ); + if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) ) + polarssl_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "PK - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_PK_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "PK - Read/write of file failed" ); + if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_VERSION) ) + polarssl_snprintf( buf, buflen, "PK - Unsupported key version" ); + if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_FORMAT) ) + polarssl_snprintf( buf, buflen, "PK - Invalid key tag or value" ); + if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_PK_ALG) ) + polarssl_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_REQUIRED) ) + polarssl_snprintf( buf, buflen, "PK - Private key password can't be empty" ); + if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_MISMATCH) ) + polarssl_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); + if( use_ret == -(POLARSSL_ERR_PK_INVALID_PUBKEY) ) + polarssl_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + if( use_ret == -(POLARSSL_ERR_PK_INVALID_ALG) ) + polarssl_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE) ) + polarssl_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + if( use_ret == -(POLARSSL_ERR_PK_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + if( use_ret == -(POLARSSL_ERR_PK_SIG_LEN_MISMATCH) ) + polarssl_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); +#endif /* POLARSSL_PK_C */ + +#if defined(POLARSSL_PKCS12_C) + if( use_ret == -(POLARSSL_ERR_PKCS12_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + if( use_ret == -(POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT) ) + polarssl_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); + if( use_ret == -(POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH) ) + polarssl_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* POLARSSL_PKCS12_C */ + +#if defined(POLARSSL_PKCS5_C) + if( use_ret == -(POLARSSL_ERR_PKCS5_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_PKCS5_INVALID_FORMAT) ) + polarssl_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); + if( use_ret == -(POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); + if( use_ret == -(POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH) ) + polarssl_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* POLARSSL_PKCS5_C */ + +#if defined(POLARSSL_RSA_C) + if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) ) + polarssl_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); + if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) ) + polarssl_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); + if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) ) + polarssl_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" ); + if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) ) + polarssl_snprintf( buf, buflen, "RSA - The public key operation failed" ); + if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) ) + polarssl_snprintf( buf, buflen, "RSA - The private key operation failed" ); + if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) ) + polarssl_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); + if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) ) + polarssl_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); + if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) ) + polarssl_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_SSL_TLS_C) + if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) ) + polarssl_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) ) + polarssl_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) ) + polarssl_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) ) + polarssl_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) ) + polarssl_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_RNG) ) + polarssl_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + polarssl_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + polarssl_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) ) + polarssl_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + polarssl_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) ) + polarssl_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) ) + polarssl_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + polarssl_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) ) + polarssl_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) ) + polarssl_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FAILED) ) + polarssl_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + polarssl_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(POLARSSL_ERR_SSL_COMPRESSION_FAILED) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + polarssl_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + polarssl_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED) ) + polarssl_snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(POLARSSL_ERR_SSL_PK_TYPE_MISMATCH) ) + polarssl_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_IDENTITY) ) + polarssl_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(POLARSSL_ERR_SSL_INTERNAL_ERROR) ) + polarssl_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(POLARSSL_ERR_SSL_COUNTER_WRAPPING) ) + polarssl_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + polarssl_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + polarssl_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); +#endif /* POLARSSL_SSL_TLS_C */ + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) + if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_OID) ) + polarssl_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_FORMAT) ) + polarssl_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_VERSION) ) + polarssl_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_SERIAL) ) + polarssl_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_ALG) ) + polarssl_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_NAME) ) + polarssl_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_DATE) ) + polarssl_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_SIGNATURE) ) + polarssl_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_EXTENSIONS) ) + polarssl_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_VERSION) ) + polarssl_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_SIG_ALG) ) + polarssl_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(POLARSSL_ERR_X509_SIG_MISMATCH) ) + polarssl_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::x509_crt sig_oid)" ); + if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) ) + polarssl_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) ) + polarssl_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(POLARSSL_ERR_X509_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "X509 - Read/write of file failed" ); +#endif /* POLARSSL_X509_USE,X509_CREATE_C */ + // END generated code + + if( strlen( buf ) == 0 ) + polarssl_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; + + polarssl_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +#if defined(POLARSSL_AES_C) + if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) ) + polarssl_snprintf( buf, buflen, "AES - Invalid key length" ); + if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) ) + polarssl_snprintf( buf, buflen, "AES - Invalid data input length" ); +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_ASN1_PARSE_C) + if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) ) + polarssl_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); + if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) ) + polarssl_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); + if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) ) + polarssl_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); + if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) ) + polarssl_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); + if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) ) + polarssl_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); + if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); + if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) ) + polarssl_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* POLARSSL_ASN1_PARSE_C */ + +#if defined(POLARSSL_BASE64_C) + if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) ) + polarssl_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); + if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) ) + polarssl_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); +#endif /* POLARSSL_BASE64_C */ + +#if defined(POLARSSL_BIGNUM_C) + if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); + if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) ) + polarssl_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); + if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) ) + polarssl_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); + if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) ) + polarssl_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); + if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) ) + polarssl_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); + if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) ) + polarssl_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); + if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) ) + polarssl_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); +#endif /* POLARSSL_BIGNUM_C */ + +#if defined(POLARSSL_BLOWFISH_C) + if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) + polarssl_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); + if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) + polarssl_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); +#endif /* POLARSSL_BLOWFISH_C */ + +#if defined(POLARSSL_CAMELLIA_C) + if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) + polarssl_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); + if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) + polarssl_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_CCM_C) + if( use_ret == -(POLARSSL_ERR_CCM_BAD_INPUT) ) + polarssl_snprintf( buf, buflen, "CCM - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_CCM_AUTH_FAILED) ) + polarssl_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); +#endif /* POLARSSL_CCM_C */ + +#if defined(POLARSSL_CTR_DRBG_C) + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) + polarssl_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) + polarssl_snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) ) + polarssl_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); +#endif /* POLARSSL_CTR_DRBG_C */ + +#if defined(POLARSSL_DES_C) + if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) ) + polarssl_snprintf( buf, buflen, "DES - The data input has an invalid length" ); +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ENTROPY_C) + if( use_ret == -(POLARSSL_ERR_ENTROPY_SOURCE_FAILED) ) + polarssl_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); + if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) ) + polarssl_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); + if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) ) + polarssl_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); + if( use_ret == -(POLARSSL_ERR_ENTROPY_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); +#endif /* POLARSSL_ENTROPY_C */ + +#if defined(POLARSSL_GCM_C) + if( use_ret == -(POLARSSL_ERR_GCM_AUTH_FAILED) ) + polarssl_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); + if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) ) + polarssl_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_HMAC_DRBG_C) + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) + polarssl_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) + polarssl_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) + polarssl_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); +#endif /* POLARSSL_HMAC_DRBG_C */ + +#if defined(POLARSSL_MD2_C) + if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "MD2 - Read/write error in file" ); +#endif /* POLARSSL_MD2_C */ + +#if defined(POLARSSL_MD4_C) + if( use_ret == -(POLARSSL_ERR_MD4_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "MD4 - Read/write error in file" ); +#endif /* POLARSSL_MD4_C */ + +#if defined(POLARSSL_MD5_C) + if( use_ret == -(POLARSSL_ERR_MD5_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "MD5 - Read/write error in file" ); +#endif /* POLARSSL_MD5_C */ + +#if defined(POLARSSL_NET_C) + if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) ) + polarssl_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) ) + polarssl_snprintf( buf, buflen, "NET - Failed to open a socket" ); + if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) ) + polarssl_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); + if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) ) + polarssl_snprintf( buf, buflen, "NET - Binding of the socket failed" ); + if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) ) + polarssl_snprintf( buf, buflen, "NET - Could not listen on the socket" ); + if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) ) + polarssl_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); + if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) ) + polarssl_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); + if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) ) + polarssl_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); + if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) ) + polarssl_snprintf( buf, buflen, "NET - Connection was reset by peer" ); + if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) ) + polarssl_snprintf( buf, buflen, "NET - Connection requires a read call" ); + if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) ) + polarssl_snprintf( buf, buflen, "NET - Connection requires a write call" ); +#endif /* POLARSSL_NET_C */ + +#if defined(POLARSSL_OID_C) + if( use_ret == -(POLARSSL_ERR_OID_NOT_FOUND) ) + polarssl_snprintf( buf, buflen, "OID - OID is not found" ); + if( use_ret == -(POLARSSL_ERR_OID_BUF_TOO_SMALL) ) + polarssl_snprintf( buf, buflen, "OID - output buffer is too small" ); +#endif /* POLARSSL_OID_C */ + +#if defined(POLARSSL_PADLOCK_C) + if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) ) + polarssl_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); +#endif /* POLARSSL_PADLOCK_C */ + +#if defined(POLARSSL_PBKDF2_C) + if( use_ret == -(POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "PBKDF2 - Bad input parameters to function" ); +#endif /* POLARSSL_PBKDF2_C */ + +#if defined(POLARSSL_RIPEMD160_C) + if( use_ret == -(POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "RIPEMD160 - Read/write error in file" ); +#endif /* POLARSSL_RIPEMD160_C */ + +#if defined(POLARSSL_SHA1_C) + if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "SHA1 - Read/write error in file" ); +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + if( use_ret == -(POLARSSL_ERR_SHA256_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "SHA256 - Read/write error in file" ); +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + if( use_ret == -(POLARSSL_ERR_SHA512_FILE_IO_ERROR) ) + polarssl_snprintf( buf, buflen, "SHA512 - Read/write error in file" ); +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_THREADING_C) + if( use_ret == -(POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE) ) + polarssl_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); + if( use_ret == -(POLARSSL_ERR_THREADING_BAD_INPUT_DATA) ) + polarssl_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_THREADING_MUTEX_ERROR) ) + polarssl_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* POLARSSL_THREADING_C */ + +#if defined(POLARSSL_XTEA_C) + if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) ) + polarssl_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); +#endif /* POLARSSL_XTEA_C */ + // END generated code + + if( strlen( buf ) != 0 ) + return; + + polarssl_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); +} + +#if defined(POLARSSL_ERROR_STRERROR_BC) +void error_strerror( int ret, char *buf, size_t buflen ) +{ + polarssl_strerror( ret, buf, buflen ); +} +#endif /* POLARSSL_ERROR_STRERROR_BC */ + +#else /* POLARSSL_ERROR_C */ + +#if defined(POLARSSL_ERROR_STRERROR_DUMMY) + +/* + * Provide an non-function in case POLARSSL_ERROR_C is not defined + */ +void polarssl_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#if defined(POLARSSL_ERROR_STRERROR_BC) +void error_strerror( int ret, char *buf, size_t buflen ) +{ + polarssl_strerror( ret, buf, buflen ); +} +#endif /* POLARSSL_ERROR_STRERROR_BC */ +#endif /* POLARSSL_ERROR_STRERROR_DUMMY */ + +#endif /* POLARSSL_ERROR_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/gcm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/gcm.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,947 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_GCM_C) + +#include "polarssl/gcm.h" + +#include <string.h> + +#if defined(POLARSSL_AESNI_C) +#include "polarssl/aesni.h" +#endif + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST && POLARSSL_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 polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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( 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 = 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(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( aesni_supports( POLARSSL_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 gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key, + unsigned int keysize ) +{ + int ret; + const cipher_info_t *cipher_info; + + memset( ctx, 0, sizeof(gcm_context) ); + + cipher_init( &ctx->cipher_ctx ); + + cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( POLARSSL_ERR_GCM_BAD_INPUT ); + + cipher_free( &ctx->cipher_ctx ); + + if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize, + POLARSSL_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( 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(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_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 ); + + aesni_gcm_mult( output, x, h ); + return; + } +#endif /* POLARSSL_AESNI_C && POLARSSL_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 gcm_starts( 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( POLARSSL_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 = 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 gcm_update( 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( POLARSSL_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 > 0x03FFFFE0ull ) + { + return( POLARSSL_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 = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == 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 gcm_finish( 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( POLARSSL_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 gcm_crypt_and_tag( 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 = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int gcm_auth_decrypt( 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 = gcm_crypt_and_tag( ctx, 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 ) + { + polarssl_zeroize( output, length ); + return( POLARSSL_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void gcm_free( gcm_context *ctx ) +{ + cipher_free( &ctx->cipher_ctx ); + polarssl_zeroize( ctx, sizeof( gcm_context ) ); +} + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_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 gcm_self_test( int verbose ) +{ + gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + cipher_id_t cipher = POLARSSL_CIPHER_ID_AES; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_crypt_and_tag( &ctx, 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_crypt_and_tag( &ctx, 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_starts( &ctx, GCM_ENCRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, + buf + 32 ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + ret = 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_starts( &ctx, GCM_DECRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + ret = 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + } + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */ + +#endif /* POLARSSL_GCM_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/havege.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/havege.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,245 @@ +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_HAVEGE_C) + +#include "polarssl/havege.h" +#include "polarssl/timing.h" + +#include <string.h> + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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) 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) 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 % COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( 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 < COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void havege_init( havege_state *hs ) +{ + memset( hs, 0, sizeof( havege_state ) ); + + havege_fill( hs ); +} + +void havege_free( havege_state *hs ) +{ + if( hs == NULL ) + return; + + polarssl_zeroize( hs, sizeof( havege_state ) ); +} + +/* + * HAVEGE rand function + */ +int havege_random( void *p_rng, unsigned char *buf, size_t len ) +{ + int val; + size_t use_len; + havege_state *hs = (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] >= 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 /* POLARSSL_HAVEGE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/hmac_drbg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/hmac_drbg.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,503 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright (C) 2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_HMAC_DRBG_C) + +#include "polarssl/hmac_drbg.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_SELF_TEST */ +#endif /* POLARSSL_PLATFORM_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +void hmac_drbg_update( hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + size_t md_len = ctx->md_ctx.md_info->size; + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[POLARSSL_MD_MAX_SIZE]; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + md_hmac_reset( &ctx->md_ctx ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( rounds == 2 ) + md_hmac_update( &ctx->md_ctx, additional, add_len ); + md_hmac_finish( &ctx->md_ctx, K ); + + /* Step 2 or 5 */ + md_hmac_starts( &ctx->md_ctx, K, md_len ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_finish( &ctx->md_ctx, ctx->V ); + } +} + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int hmac_drbg_init_buf( hmac_drbg_context *ctx, + const md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret; + + memset( ctx, 0, sizeof( hmac_drbg_context ) ); + + md_init( &ctx->md_ctx ); + + if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 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. + */ + md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size ); + memset( ctx->V, 0x01, md_info->size ); + + hmac_drbg_update( ctx, data, data_len ); + + return( 0 ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) + */ +int hmac_drbg_reseed( hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen; + + /* III. Check input length */ + if( len > POLARSSL_HMAC_DRBG_MAX_INPUT || + ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + memset( seed, 0, POLARSSL_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( POLARSSL_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 */ + 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 hmac_drbg_init( hmac_drbg_context *ctx, + const 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; + + memset( ctx, 0, sizeof( hmac_drbg_context ) ); + + md_init( &ctx->md_ctx ); + + if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 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. + */ + md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size ); + memset( ctx->V, 0x01, md_info->size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->reseed_interval = POLARSSL_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_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_info->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 = hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + ctx->entropy_len = entropy_len; + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for reseeds + */ +void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void hmac_drbg_set_reseed_interval( 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 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; + hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng; + size_t md_len = md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST ) + return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT ) + return( POLARSSL_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 == POLARSSL_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = 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 ) + 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; + + md_hmac_reset( &ctx->md_ctx ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_finish( &ctx->md_ctx, ctx->V ); + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + hmac_drbg_update( ctx, additional, add_len ); + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + + /* 8. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG random function + */ +int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) ); +} + +/* + * Free an HMAC_DRBG context + */ +void hmac_drbg_free( hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + + md_free( &ctx->md_ctx ); + + polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) ); +} + +#if defined(POLARSSL_FS_IO) +int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path ) +{ + int ret; + FILE *f; + unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > POLARSSL_HMAC_DRBG_MAX_INPUT ) + { + fclose( f ); + return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); + } + + fclose( f ); + + hmac_drbg_update( ctx, buf, n ); + + return( hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* POLARSSL_FS_IO */ + + +#if defined(POLARSSL_SELF_TEST) + +#if !defined(POLARSSL_SHA1_C) +/* Dummy checkup routine */ +int hmac_drbg_self_test( int verbose ) +{ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + 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 ) \ + polarssl_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int hmac_drbg_self_test( int verbose ) +{ + hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 ); + + /* + * PR = True + */ + if( verbose != 0 ) + polarssl_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( hmac_drbg_init( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + polarssl_printf( " HMAC_DRBG (PR = False) : " ); + + test_offset = 0; + CHK( hmac_drbg_init( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_HMAC_DRBG_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/md.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/md.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,342 @@ +/** + * \file md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD_C) + +#include "polarssl/md.h" +#include "polarssl/md_wrap.h" + +#include <stdlib.h> +#include <string.h> + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static const int supported_digests[] = { + +#if defined(POLARSSL_SHA512_C) + POLARSSL_MD_SHA512, + POLARSSL_MD_SHA384, +#endif + +#if defined(POLARSSL_SHA256_C) + POLARSSL_MD_SHA256, + POLARSSL_MD_SHA224, +#endif + +#if defined(POLARSSL_SHA1_C) + POLARSSL_MD_SHA1, +#endif + +#if defined(POLARSSL_RIPEMD160_C) + POLARSSL_MD_RIPEMD160, +#endif + +#if defined(POLARSSL_MD5_C) + POLARSSL_MD_MD5, +#endif + +#if defined(POLARSSL_MD4_C) + POLARSSL_MD_MD4, +#endif + +#if defined(POLARSSL_MD2_C) + POLARSSL_MD_MD2, +#endif + + POLARSSL_MD_NONE +}; + +const int *md_list( void ) +{ + return( supported_digests ); +} + +const md_info_t *md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(POLARSSL_MD2_C) + if( !strcasecmp( "MD2", md_name ) ) + return md_info_from_type( POLARSSL_MD_MD2 ); +#endif +#if defined(POLARSSL_MD4_C) + if( !strcasecmp( "MD4", md_name ) ) + return md_info_from_type( POLARSSL_MD_MD4 ); +#endif +#if defined(POLARSSL_MD5_C) + if( !strcasecmp( "MD5", md_name ) ) + return md_info_from_type( POLARSSL_MD_MD5 ); +#endif +#if defined(POLARSSL_RIPEMD160_C) + if( !strcasecmp( "RIPEMD160", md_name ) ) + return md_info_from_type( POLARSSL_MD_RIPEMD160 ); +#endif +#if defined(POLARSSL_SHA1_C) + if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA1 ); +#endif +#if defined(POLARSSL_SHA256_C) + if( !strcasecmp( "SHA224", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA224 ); + if( !strcasecmp( "SHA256", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA256 ); +#endif +#if defined(POLARSSL_SHA512_C) + if( !strcasecmp( "SHA384", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA384 ); + if( !strcasecmp( "SHA512", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA512 ); +#endif + return( NULL ); +} + +const md_info_t *md_info_from_type( md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(POLARSSL_MD2_C) + case POLARSSL_MD_MD2: + return( &md2_info ); +#endif +#if defined(POLARSSL_MD4_C) + case POLARSSL_MD_MD4: + return( &md4_info ); +#endif +#if defined(POLARSSL_MD5_C) + case POLARSSL_MD_MD5: + return( &md5_info ); +#endif +#if defined(POLARSSL_RIPEMD160_C) + case POLARSSL_MD_RIPEMD160: + return( &ripemd160_info ); +#endif +#if defined(POLARSSL_SHA1_C) + case POLARSSL_MD_SHA1: + return( &sha1_info ); +#endif +#if defined(POLARSSL_SHA256_C) + case POLARSSL_MD_SHA224: + return( &sha224_info ); + case POLARSSL_MD_SHA256: + return( &sha256_info ); +#endif +#if defined(POLARSSL_SHA512_C) + case POLARSSL_MD_SHA384: + return( &sha384_info ); + case POLARSSL_MD_SHA512: + return( &sha512_info ); +#endif + default: + return( NULL ); + } +} + +void md_init( md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( md_context_t ) ); +} + +void md_free( md_context_t *ctx ) +{ + if( ctx == NULL ) + return; + + if( ctx->md_ctx ) + ctx->md_info->ctx_free_func( ctx->md_ctx ); + + polarssl_zeroize( ctx, sizeof( md_context_t ) ); +} + +int md_init_ctx( md_context_t *ctx, const md_info_t *md_info ) +{ + if( md_info == NULL || ctx == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( md_context_t ) ); + + if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) + return( POLARSSL_ERR_MD_ALLOC_FAILED ); + + ctx->md_info = md_info; + + md_info->starts_func( ctx->md_ctx ); + + return( 0 ); +} + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +int md_free_ctx( md_context_t *ctx ) +{ + md_free( ctx ); + + return( 0 ); +} +#endif + +int md_starts( md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->starts_func( ctx->md_ctx ); + + return( 0 ); +} + +int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int md_finish( md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int md( const md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + md_info->digest_func( input, ilen, output ); + + return( 0 ); +} + +int md_file( const md_info_t *md_info, const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + int ret; +#endif + + if( md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + +#if defined(POLARSSL_FS_IO) + ret = md_info->file_func( path, output ); + if( ret != 0 ) + return( POLARSSL_ERR_MD_FILE_IO_ERROR + ret ); + + return( ret ); +#else + ((void) path); + ((void) output); + + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_FS_IO */ +} + +int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen ); + + return( 0 ); +} + +int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int md_hmac_finish( md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int md_hmac_reset( md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_reset_func( ctx->md_ctx ); + + return( 0 ); +} + +int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + md_info->hmac_func( key, keylen, input, ilen, output ); + + return( 0 ); +} + +int md_process( md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->process_func( ctx->md_ctx, data ); + + return( 0 ); +} + +#endif /* POLARSSL_MD_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/md2.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/md2.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,401 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD2_C) + +#include "polarssl/md2.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_MD2_ALT) + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +void md2_init( md2_context *ctx ) +{ + memset( ctx, 0, sizeof( md2_context ) ); +} + +void md2_free( md2_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( md2_context ) ); +} + +/* + * MD2 context setup + */ +void md2_starts( md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; +} + +void md2_process( 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]; + } +} + +/* + * MD2 process buffer + */ +void md2_update( 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; + md2_process( ctx ); + } + } +} + +/* + * MD2 final digest + */ +void md2_finish( 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; + + md2_process( ctx ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + md2_process( ctx ); + + memcpy( output, ctx->state, 16 ); +} + +#endif /* !POLARSSL_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + md2_context ctx; + + md2_init( &ctx ); + md2_starts( &ctx ); + md2_update( &ctx, input, ilen ); + md2_finish( &ctx, output ); + md2_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = MD2( file contents ) + */ +int md2_file( const char *path, unsigned char output[16] ) +{ + FILE *f; + size_t n; + md2_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); + + md2_init( &ctx ); + md2_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md2_update( &ctx, buf, n ); + + md2_finish( &ctx, output ); + md2_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * MD2 HMAC context setup + */ +void md2_hmac_starts( md2_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[16]; + + if( keylen > 16 ) + { + md2( key, keylen, sum ); + keylen = 16; + key = sum; + } + + memset( ctx->ipad, 0x36, 16 ); + memset( ctx->opad, 0x5C, 16 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + md2_starts( ctx ); + md2_update( ctx, ctx->ipad, 16 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * MD2 HMAC process buffer + */ +void md2_hmac_update( md2_context *ctx, const unsigned char *input, + size_t ilen ) +{ + md2_update( ctx, input, ilen ); +} + +/* + * MD2 HMAC final digest + */ +void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ) +{ + unsigned char tmpbuf[16]; + + md2_finish( ctx, tmpbuf ); + md2_starts( ctx ); + md2_update( ctx, ctx->opad, 16 ); + md2_update( ctx, tmpbuf, 16 ); + md2_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * MD2 HMAC context reset + */ +void md2_hmac_reset( md2_context *ctx ) +{ + md2_starts( ctx ); + md2_update( ctx, ctx->ipad, 16 ); +} + +/* + * output = HMAC-MD2( hmac key, input buffer ) + */ +void md2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ) +{ + md2_context ctx; + + md2_init( &ctx ); + md2_hmac_starts( &ctx, key, keylen ); + md2_hmac_update( &ctx, input, ilen ); + md2_hmac_finish( &ctx, output ); + md2_free( &ctx ); +} + +#if defined(POLARSSL_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 md2_self_test( int verbose ) +{ + int i; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " MD2 test #%d: ", i + 1 ); + + 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_MD2_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/md4.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/md4.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,497 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD4_C) + +#include "polarssl/md4.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_MD4_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void md4_init( md4_context *ctx ) +{ + memset( ctx, 0, sizeof( md4_context ) ); +} + +void md4_free( md4_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( md4_context ) ); +} + +/* + * MD4 context setup + */ +void md4_starts( 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; +} + +void md4_process( 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; +} + +/* + * MD4 process buffer + */ +void md4_update( 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 ); + md4_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + 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 md4_finish( 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 ); + + md4_update( ctx, (unsigned char *) md4_padding, padn ); + 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 /* !POLARSSL_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +void md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + md4_context ctx; + + md4_init( &ctx ); + md4_starts( &ctx ); + md4_update( &ctx, input, ilen ); + md4_finish( &ctx, output ); + md4_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = MD4( file contents ) + */ +int md4_file( const char *path, unsigned char output[16] ) +{ + FILE *f; + size_t n; + md4_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_MD4_FILE_IO_ERROR ); + + md4_init( &ctx ); + md4_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md4_update( &ctx, buf, n ); + + md4_finish( &ctx, output ); + md4_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_MD4_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * MD4 HMAC context setup + */ +void md4_hmac_starts( md4_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[16]; + + if( keylen > 64 ) + { + md4( key, keylen, sum ); + keylen = 16; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + md4_starts( ctx ); + md4_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * MD4 HMAC process buffer + */ +void md4_hmac_update( md4_context *ctx, const unsigned char *input, + size_t ilen ) +{ + md4_update( ctx, input, ilen ); +} + +/* + * MD4 HMAC final digest + */ +void md4_hmac_finish( md4_context *ctx, unsigned char output[16] ) +{ + unsigned char tmpbuf[16]; + + md4_finish( ctx, tmpbuf ); + md4_starts( ctx ); + md4_update( ctx, ctx->opad, 64 ); + md4_update( ctx, tmpbuf, 16 ); + md4_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * MD4 HMAC context reset + */ +void md4_hmac_reset( md4_context *ctx ) +{ + md4_starts( ctx ); + md4_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-MD4( hmac key, input buffer ) + */ +void md4_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ) +{ + md4_context ctx; + + md4_init( &ctx ); + md4_hmac_starts( &ctx, key, keylen ); + md4_hmac_update( &ctx, input, ilen ); + md4_hmac_finish( &ctx, output ); + md4_free( &ctx ); +} + +#if defined(POLARSSL_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 md4_self_test( int verbose ) +{ + int i; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " MD4 test #%d: ", i + 1 ); + + 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_MD4_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/md5.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/md5.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,618 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD5_C) + +#include "polarssl/md5.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_MD5_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void md5_init( md5_context *ctx ) +{ + memset( ctx, 0, sizeof( md5_context ) ); +} + +void md5_free( md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( md5_context ) ); +} + +/* + * MD5 context setup + */ +void md5_starts( 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; +} + +void md5_process( 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; +} + +/* + * MD5 process buffer + */ +void md5_update( 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 ); + md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + 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 md5_finish( 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 ); + + md5_update( ctx, md5_padding, padn ); + 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 /* !POLARSSL_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + md5_context ctx; + + md5_init( &ctx ); + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); + md5_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = MD5( file contents ) + */ +int md5_file( const char *path, unsigned char output[16] ) +{ + FILE *f; + size_t n; + md5_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_MD5_FILE_IO_ERROR ); + + md5_init( &ctx ); + md5_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md5_update( &ctx, buf, n ); + + md5_finish( &ctx, output ); + md5_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_MD5_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * MD5 HMAC context setup + */ +void md5_hmac_starts( md5_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[16]; + + if( keylen > 64 ) + { + md5( key, keylen, sum ); + keylen = 16; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + md5_starts( ctx ); + md5_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * MD5 HMAC process buffer + */ +void md5_hmac_update( md5_context *ctx, const unsigned char *input, + size_t ilen ) +{ + md5_update( ctx, input, ilen ); +} + +/* + * MD5 HMAC final digest + */ +void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ) +{ + unsigned char tmpbuf[16]; + + md5_finish( ctx, tmpbuf ); + md5_starts( ctx ); + md5_update( ctx, ctx->opad, 64 ); + md5_update( ctx, tmpbuf, 16 ); + md5_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * MD5 HMAC context reset + */ +void md5_hmac_reset( md5_context *ctx ) +{ + md5_starts( ctx ); + md5_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-MD5( hmac key, input buffer ) + */ +void md5_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ) +{ + md5_context ctx; + + md5_init( &ctx ); + md5_hmac_starts( &ctx, key, keylen ); + md5_hmac_update( &ctx, input, ilen ); + md5_hmac_finish( &ctx, output ); + md5_free( &ctx ); +} + +#if defined(POLARSSL_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 } +}; + +/* + * RFC 2202 test vectors + */ +static const unsigned char md5_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 80 times */ + { "" } +}; + +static const int md5_hmac_test_keylen[7] = +{ + 16, 4, 16, 25, 16, 80, 80 +}; + +static const unsigned char md5_hmac_test_buf[7][74] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "Test Using Larger Than Block-Size Key and Larger" + " Than One Block-Size Data" } +}; + +static const int md5_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 73 +}; + +static const unsigned char md5_hmac_test_sum[7][16] = +{ + { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C, + 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D }, + { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03, + 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 }, + { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88, + 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 }, + { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA, + 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 }, + { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00, + 0xF9, 0xBA, 0xB9, 0x95 }, + { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F, + 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD }, + { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE, + 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E } +}; + +/* + * Checkup routine + */ +int md5_self_test( int verbose ) +{ + int i, buflen; + unsigned char buf[1024]; + unsigned char md5sum[16]; + md5_context ctx; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " MD5 test #%d: ", i + 1 ); + + md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " HMAC-MD5 test #%d: ", i + 1 ); + + if( i == 5 || i == 6 ) + { + memset( buf, 0xAA, buflen = 80 ); + md5_hmac_starts( &ctx, buf, buflen ); + } + else + md5_hmac_starts( &ctx, md5_hmac_test_key[i], + md5_hmac_test_keylen[i] ); + + md5_hmac_update( &ctx, md5_hmac_test_buf[i], + md5_hmac_test_buflen[i] ); + + md5_hmac_finish( &ctx, md5sum ); + + buflen = ( i == 4 ) ? 12 : 16; + + if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_MD5_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/md_wrap.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/md_wrap.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,952 @@ +/** + * \file md_wrap.c + + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD_C) + +#include "polarssl/md_wrap.h" + +#if defined(POLARSSL_MD2_C) +#include "polarssl/md2.h" +#endif + +#if defined(POLARSSL_MD4_C) +#include "polarssl/md4.h" +#endif + +#if defined(POLARSSL_MD5_C) +#include "polarssl/md5.h" +#endif + +#if defined(POLARSSL_RIPEMD160_C) +#include "polarssl/ripemd160.h" +#endif + +#if defined(POLARSSL_SHA1_C) +#include "polarssl/sha1.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#include "polarssl/sha256.h" +#endif + +#if defined(POLARSSL_SHA512_C) +#include "polarssl/sha512.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_MD2_C) + +static void md2_starts_wrap( void *ctx ) +{ + md2_starts( (md2_context *) ctx ); +} + +static void md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md2_update( (md2_context *) ctx, input, ilen ); +} + +static void md2_finish_wrap( void *ctx, unsigned char *output ) +{ + md2_finish( (md2_context *) ctx, output ); +} + +static int md2_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return md2_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + md2_hmac_starts( (md2_context *) ctx, key, keylen ); +} + +static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md2_hmac_update( (md2_context *) ctx, input, ilen ); +} + +static void md2_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + md2_hmac_finish( (md2_context *) ctx, output ); +} + +static void md2_hmac_reset_wrap( void *ctx ) +{ + md2_hmac_reset( (md2_context *) ctx ); +} + +static void * md2_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( md2_context ) ); +} + +static void md2_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( md2_context ) ); + polarssl_free( ctx ); +} + +static void md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + md2_process( (md2_context *) ctx ); +} + +const md_info_t md2_info = { + POLARSSL_MD_MD2, + "MD2", + 16, + md2_starts_wrap, + md2_update_wrap, + md2_finish_wrap, + md2, + md2_file_wrap, + md2_hmac_starts_wrap, + md2_hmac_update_wrap, + md2_hmac_finish_wrap, + md2_hmac_reset_wrap, + md2_hmac, + md2_ctx_alloc, + md2_ctx_free, + md2_process_wrap, +}; + +#endif /* POLARSSL_MD2_C */ + +#if defined(POLARSSL_MD4_C) + +static void md4_starts_wrap( void *ctx ) +{ + md4_starts( (md4_context *) ctx ); +} + +static void md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md4_update( (md4_context *) ctx, input, ilen ); +} + +static void md4_finish_wrap( void *ctx, unsigned char *output ) +{ + md4_finish( (md4_context *) ctx, output ); +} + +static int md4_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return md4_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + md4_hmac_starts( (md4_context *) ctx, key, keylen ); +} + +static void md4_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md4_hmac_update( (md4_context *) ctx, input, ilen ); +} + +static void md4_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + md4_hmac_finish( (md4_context *) ctx, output ); +} + +static void md4_hmac_reset_wrap( void *ctx ) +{ + md4_hmac_reset( (md4_context *) ctx ); +} + +static void *md4_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( md4_context ) ); +} + +static void md4_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( md4_context ) ); + polarssl_free( ctx ); +} + +static void md4_process_wrap( void *ctx, const unsigned char *data ) +{ + md4_process( (md4_context *) ctx, data ); +} + +const md_info_t md4_info = { + POLARSSL_MD_MD4, + "MD4", + 16, + md4_starts_wrap, + md4_update_wrap, + md4_finish_wrap, + md4, + md4_file_wrap, + md4_hmac_starts_wrap, + md4_hmac_update_wrap, + md4_hmac_finish_wrap, + md4_hmac_reset_wrap, + md4_hmac, + md4_ctx_alloc, + md4_ctx_free, + md4_process_wrap, +}; + +#endif /* POLARSSL_MD4_C */ + +#if defined(POLARSSL_MD5_C) + +static void md5_starts_wrap( void *ctx ) +{ + md5_starts( (md5_context *) ctx ); +} + +static void md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md5_update( (md5_context *) ctx, input, ilen ); +} + +static void md5_finish_wrap( void *ctx, unsigned char *output ) +{ + md5_finish( (md5_context *) ctx, output ); +} + +static int md5_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return md5_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + md5_hmac_starts( (md5_context *) ctx, key, keylen ); +} + +static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md5_hmac_update( (md5_context *) ctx, input, ilen ); +} + +static void md5_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + md5_hmac_finish( (md5_context *) ctx, output ); +} + +static void md5_hmac_reset_wrap( void *ctx ) +{ + md5_hmac_reset( (md5_context *) ctx ); +} + +static void * md5_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( md5_context ) ); +} + +static void md5_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( md5_context ) ); + polarssl_free( ctx ); +} + +static void md5_process_wrap( void *ctx, const unsigned char *data ) +{ + md5_process( (md5_context *) ctx, data ); +} + +const md_info_t md5_info = { + POLARSSL_MD_MD5, + "MD5", + 16, + md5_starts_wrap, + md5_update_wrap, + md5_finish_wrap, + md5, + md5_file_wrap, + md5_hmac_starts_wrap, + md5_hmac_update_wrap, + md5_hmac_finish_wrap, + md5_hmac_reset_wrap, + md5_hmac, + md5_ctx_alloc, + md5_ctx_free, + md5_process_wrap, +}; + +#endif /* POLARSSL_MD5_C */ + +#if defined(POLARSSL_RIPEMD160_C) + +static void ripemd160_starts_wrap( void *ctx ) +{ + ripemd160_starts( (ripemd160_context *) ctx ); +} + +static void ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + ripemd160_update( (ripemd160_context *) ctx, input, ilen ); +} + +static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + ripemd160_finish( (ripemd160_context *) ctx, output ); +} + +static int ripemd160_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return ripemd160_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void ripemd160_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + ripemd160_hmac_starts( (ripemd160_context *) ctx, key, keylen ); +} + +static void ripemd160_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + ripemd160_hmac_update( (ripemd160_context *) ctx, input, ilen ); +} + +static void ripemd160_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + ripemd160_hmac_finish( (ripemd160_context *) ctx, output ); +} + +static void ripemd160_hmac_reset_wrap( void *ctx ) +{ + ripemd160_hmac_reset( (ripemd160_context *) ctx ); +} + +static void * ripemd160_ctx_alloc( void ) +{ + ripemd160_context *ctx; + ctx = polarssl_malloc( sizeof( ripemd160_context ) ); + + if( ctx == NULL ) + return( NULL ); + + ripemd160_init( ctx ); + + return( ctx ); +} + +static void ripemd160_ctx_free( void *ctx ) +{ + ripemd160_free( (ripemd160_context *) ctx ); + polarssl_free( ctx ); +} + +static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + ripemd160_process( (ripemd160_context *) ctx, data ); +} + +const md_info_t ripemd160_info = { + POLARSSL_MD_RIPEMD160, + "RIPEMD160", + 20, + ripemd160_starts_wrap, + ripemd160_update_wrap, + ripemd160_finish_wrap, + ripemd160, + ripemd160_file_wrap, + ripemd160_hmac_starts_wrap, + ripemd160_hmac_update_wrap, + ripemd160_hmac_finish_wrap, + ripemd160_hmac_reset_wrap, + ripemd160_hmac, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_process_wrap, +}; + +#endif /* POLARSSL_RIPEMD160_C */ + +#if defined(POLARSSL_SHA1_C) + +static void sha1_starts_wrap( void *ctx ) +{ + sha1_starts( (sha1_context *) ctx ); +} + +static void sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha1_update( (sha1_context *) ctx, input, ilen ); +} + +static void sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + sha1_finish( (sha1_context *) ctx, output ); +} + +static int sha1_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha1_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha1_hmac_starts( (sha1_context *) ctx, key, keylen ); +} + +static void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha1_hmac_update( (sha1_context *) ctx, input, ilen ); +} + +static void sha1_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha1_hmac_finish( (sha1_context *) ctx, output ); +} + +static void sha1_hmac_reset_wrap( void *ctx ) +{ + sha1_hmac_reset( (sha1_context *) ctx ); +} + +static void * sha1_ctx_alloc( void ) +{ + sha1_context *ctx; + ctx = polarssl_malloc( sizeof( sha1_context ) ); + + if( ctx == NULL ) + return( NULL ); + + sha1_init( ctx ); + + return( ctx ); +} + +static void sha1_ctx_free( void *ctx ) +{ + sha1_free( (sha1_context *) ctx ); + polarssl_free( ctx ); +} + +static void sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + sha1_process( (sha1_context *) ctx, data ); +} + +const md_info_t sha1_info = { + POLARSSL_MD_SHA1, + "SHA1", + 20, + sha1_starts_wrap, + sha1_update_wrap, + sha1_finish_wrap, + sha1, + sha1_file_wrap, + sha1_hmac_starts_wrap, + sha1_hmac_update_wrap, + sha1_hmac_finish_wrap, + sha1_hmac_reset_wrap, + sha1_hmac, + sha1_ctx_alloc, + sha1_ctx_free, + sha1_process_wrap, +}; + +#endif /* POLARSSL_SHA1_C */ + +/* + * Wrappers for generic message digests + */ +#if defined(POLARSSL_SHA256_C) + +static void sha224_starts_wrap( void *ctx ) +{ + sha256_starts( (sha256_context *) ctx, 1 ); +} + +static void sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_finish( (sha256_context *) ctx, output ); +} + +static void sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256( input, ilen, output, 1 ); +} + +static int sha224_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha256_file( path, output, 1 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 1 ); +} + +static void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_hmac_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha224_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_hmac_finish( (sha256_context *) ctx, output ); +} + +static void sha224_hmac_reset_wrap( void *ctx ) +{ + sha256_hmac_reset( (sha256_context *) ctx ); +} + +static void sha224_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256_hmac( key, keylen, input, ilen, output, 1 ); +} + +static void * sha224_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( sha256_context ) ); +} + +static void sha224_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( sha256_context ) ); + polarssl_free( ctx ); +} + +static void sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + sha256_process( (sha256_context *) ctx, data ); +} + +const md_info_t sha224_info = { + POLARSSL_MD_SHA224, + "SHA224", + 28, + sha224_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha224_wrap, + sha224_file_wrap, + sha224_hmac_starts_wrap, + sha224_hmac_update_wrap, + sha224_hmac_finish_wrap, + sha224_hmac_reset_wrap, + sha224_hmac_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_process_wrap, +}; + +static void sha256_starts_wrap( void *ctx ) +{ + sha256_starts( (sha256_context *) ctx, 0 ); +} + +static void sha256_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha256_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_finish( (sha256_context *) ctx, output ); +} + +static void sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256( input, ilen, output, 0 ); +} + +static int sha256_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha256_file( path, output, 0 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 0 ); +} + +static void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_hmac_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha256_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_hmac_finish( (sha256_context *) ctx, output ); +} + +static void sha256_hmac_reset_wrap( void *ctx ) +{ + sha256_hmac_reset( (sha256_context *) ctx ); +} + +static void sha256_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256_hmac( key, keylen, input, ilen, output, 0 ); +} + +static void * sha256_ctx_alloc( void ) +{ + sha256_context *ctx; + ctx = polarssl_malloc( sizeof( sha256_context ) ); + + if( ctx == NULL ) + return( NULL ); + + sha256_init( ctx ); + + return( ctx ); +} + +static void sha256_ctx_free( void *ctx ) +{ + sha256_free( (sha256_context *) ctx ); + polarssl_free( ctx ); +} + +static void sha256_process_wrap( void *ctx, const unsigned char *data ) +{ + sha256_process( (sha256_context *) ctx, data ); +} + +const md_info_t sha256_info = { + POLARSSL_MD_SHA256, + "SHA256", + 32, + sha256_starts_wrap, + sha256_update_wrap, + sha256_finish_wrap, + sha256_wrap, + sha256_file_wrap, + sha256_hmac_starts_wrap, + sha256_hmac_update_wrap, + sha256_hmac_finish_wrap, + sha256_hmac_reset_wrap, + sha256_hmac_wrap, + sha256_ctx_alloc, + sha256_ctx_free, + sha256_process_wrap, +}; + +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + +static void sha384_starts_wrap( void *ctx ) +{ + sha512_starts( (sha512_context *) ctx, 1 ); +} + +static void sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_finish( (sha512_context *) ctx, output ); +} + +static void sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512( input, ilen, output, 1 ); +} + +static int sha384_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha512_file( path, output, 1 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 1 ); +} + +static void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_hmac_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha384_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_hmac_finish( (sha512_context *) ctx, output ); +} + +static void sha384_hmac_reset_wrap( void *ctx ) +{ + sha512_hmac_reset( (sha512_context *) ctx ); +} + +static void sha384_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512_hmac( key, keylen, input, ilen, output, 1 ); +} + +static void * sha384_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( sha512_context ) ); +} + +static void sha384_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( sha512_context ) ); + polarssl_free( ctx ); +} + +static void sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + sha512_process( (sha512_context *) ctx, data ); +} + +const md_info_t sha384_info = { + POLARSSL_MD_SHA384, + "SHA384", + 48, + sha384_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha384_wrap, + sha384_file_wrap, + sha384_hmac_starts_wrap, + sha384_hmac_update_wrap, + sha384_hmac_finish_wrap, + sha384_hmac_reset_wrap, + sha384_hmac_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_process_wrap, +}; + +static void sha512_starts_wrap( void *ctx ) +{ + sha512_starts( (sha512_context *) ctx, 0 ); +} + +static void sha512_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha512_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_finish( (sha512_context *) ctx, output ); +} + +static void sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512( input, ilen, output, 0 ); +} + +static int sha512_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha512_file( path, output, 0 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 0 ); +} + +static void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_hmac_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha512_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_hmac_finish( (sha512_context *) ctx, output ); +} + +static void sha512_hmac_reset_wrap( void *ctx ) +{ + sha512_hmac_reset( (sha512_context *) ctx ); +} + +static void sha512_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512_hmac( key, keylen, input, ilen, output, 0 ); +} + +static void * sha512_ctx_alloc( void ) +{ + sha512_context *ctx; + ctx = polarssl_malloc( sizeof( sha512_context ) ); + + if( ctx == NULL ) + return( NULL ); + + sha512_init( ctx ); + + return( ctx ); +} + +static void sha512_ctx_free( void *ctx ) +{ + sha512_free( (sha512_context *) ctx ); + polarssl_free( ctx ); +} + +static void sha512_process_wrap( void *ctx, const unsigned char *data ) +{ + sha512_process( (sha512_context *) ctx, data ); +} + +const md_info_t sha512_info = { + POLARSSL_MD_SHA512, + "SHA512", + 64, + sha512_starts_wrap, + sha512_update_wrap, + sha512_finish_wrap, + sha512_wrap, + sha512_file_wrap, + sha512_hmac_starts_wrap, + sha512_hmac_update_wrap, + sha512_hmac_finish_wrap, + sha512_hmac_reset_wrap, + sha512_hmac_wrap, + sha512_ctx_alloc, + sha512_ctx_free, + sha512_process_wrap, +}; + +#endif /* POLARSSL_SHA512_C */ + +#endif /* POLARSSL_MD_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/memory_buffer_alloc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/memory_buffer_alloc.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,735 @@ +/* + * Buffer-based memory allocator + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) +#include "polarssl/memory_buffer_alloc.h" + +/* No need for the header guard as POLARSSL_MEMORY_BUFFER_ALLOC_C + is dependent upon POLARSSL_PLATFORM_C */ +#include "polarssl/platform.h" + +#include <string.h> + +#if defined(POLARSSL_MEMORY_BACKTRACE) +#include <execinfo.h> +#endif + +#if defined(POLARSSL_THREADING_C) +#include "polarssl/threading.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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(POLARSSL_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(POLARSSL_MEMORY_DEBUG) + size_t malloc_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(POLARSSL_THREADING_C) + threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(POLARSSL_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(POLARSSL_MEMORY_BACKTRACE) + size_t i; +#endif + + polarssl_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 ); + polarssl_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(POLARSSL_MEMORY_BACKTRACE) + polarssl_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + polarssl_fprintf( stderr, "%s\n", hdr->trace[i] ); + polarssl_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain() +{ + memory_header *cur = heap.first; + + polarssl_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + polarssl_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* POLARSSL_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_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(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_malloc( size_t len ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; +#if defined(POLARSSL_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + if( len % POLARSSL_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % POLARSSL_MEMORY_ALIGN_MULTIPLE; + len += POLARSSL_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(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + polarssl_exit( 1 ); + } + +#if defined(POLARSSL_MEMORY_DEBUG) + heap.malloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + POLARSSL_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(POLARSSL_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(POLARSSL_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 & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + polarssl_exit( 1 ); + + return( ( (unsigned char *) cur ) + sizeof(memory_header) ); + } + + 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(POLARSSL_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(POLARSSL_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(POLARSSL_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 & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + polarssl_exit( 1 ); + + return( ( (unsigned char *) cur ) + sizeof(memory_header) ); +} + +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(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: polarssl_free() outside of managed " + "space\n" ); +#endif + polarssl_exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + polarssl_exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated " + "data\n" ); +#endif + polarssl_exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(POLARSSL_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(POLARSSL_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(POLARSSL_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(POLARSSL_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(POLARSSL_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(POLARSSL_MEMORY_BACKTRACE) + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + if( ( heap.verify & MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + polarssl_exit( 1 ); +} + +void memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int memory_buffer_alloc_verify() +{ + return verify_chain(); +} + +#if defined(POLARSSL_MEMORY_DEBUG) +void memory_buffer_alloc_status() +{ + polarssl_fprintf( stderr, + "Current use: %zu blocks / %zu bytes, max: %zu blocks / " + "%zu bytes (total %zu bytes), malloc / 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.malloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + polarssl_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + else + { + polarssl_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} + +void 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 memory_buffer_alloc_max_reset( void ) +{ + heap.maximum_used = 0; + heap.maximum_header_count = 0; +} + +void memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) +{ + *cur_used = heap.total_used; + *cur_blocks = heap.header_count; +} +#endif /* POLARSSL_MEMORY_DEBUG */ + +#if defined(POLARSSL_THREADING_C) +static void *buffer_alloc_malloc_mutexed( size_t len ) +{ + void *buf; + polarssl_mutex_lock( &heap.mutex ); + buf = buffer_alloc_malloc( len ); + polarssl_mutex_unlock( &heap.mutex ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + polarssl_mutex_lock( &heap.mutex ); + buffer_alloc_free( ptr ); + polarssl_mutex_unlock( &heap.mutex ); +} +#endif /* POLARSSL_THREADING_C */ + +int memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof(buffer_alloc_ctx) ); + memset( buf, 0, len ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &heap.mutex ); + platform_set_malloc_free( buffer_alloc_malloc_mutexed, + buffer_alloc_free_mutexed ); +#else + platform_set_malloc_free( buffer_alloc_malloc, buffer_alloc_free ); +#endif + + if( (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE ) + { + /* Adjust len first since buf is used in the computation */ + len -= POLARSSL_MEMORY_ALIGN_MULTIPLE + - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE; + buf += POLARSSL_MEMORY_ALIGN_MULTIPLE + - (size_t) buf % POLARSSL_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; + return( 0 ); +} + +void memory_buffer_alloc_free() +{ +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &heap.mutex ); +#endif + polarssl_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#if defined(POLARSSL_SELF_TEST) +static int check_pointer( void *p ) +{ + if( p == NULL ) + return( -1 ); + + if( (size_t) p % POLARSSL_MEMORY_ALIGN_MULTIPLE != 0 ) + return( -1 ); + + return( 0 ); +} + +static int check_all_free( ) +{ + if( +#if defined(POLARSSL_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 ) \ + polarssl_printf( "failed\n" ); \ + \ + ret = 1; \ + goto cleanup; \ + } + +int memory_buffer_alloc_self_test( int verbose ) +{ + unsigned char buf[1024]; + unsigned char *p, *q, *r, *end; + int ret = 0; + + if( verbose != 0 ) + polarssl_printf( " MBA test #1 (basic alloc-free cycle): " ); + + memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = polarssl_malloc( 1 ); + q = polarssl_malloc( 128 ); + r = polarssl_malloc( 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + polarssl_free( r ); + polarssl_free( q ); + polarssl_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + /* Memorize end to compare with the next test */ + end = heap.buf + heap.len; + + memory_buffer_alloc_free( ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " MBA test #2 (buf not aligned): " ); + + memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); + + TEST_ASSERT( heap.buf + heap.len == end ); + + p = polarssl_malloc( 1 ); + q = polarssl_malloc( 128 ); + r = polarssl_malloc( 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + polarssl_free( r ); + polarssl_free( q ); + polarssl_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + memory_buffer_alloc_free( ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " MBA test #3 (full): " ); + + memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = polarssl_malloc( sizeof( buf ) - sizeof( memory_header ) ); + + TEST_ASSERT( check_pointer( p ) == 0 ); + TEST_ASSERT( polarssl_malloc( 1 ) == NULL ); + + polarssl_free( p ); + + p = polarssl_malloc( sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); + q = polarssl_malloc( 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); + TEST_ASSERT( polarssl_malloc( 1 ) == NULL ); + + polarssl_free( q ); + + TEST_ASSERT( polarssl_malloc( 17 ) == NULL ); + + polarssl_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + memory_buffer_alloc_free( ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + +cleanup: + memory_buffer_alloc_free( ); + + return( ret ); +} +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/net.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/net.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,587 @@ +/* + * TCP networking functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_NET_C) + +#include "polarssl/net.h" + +#include <string.h> + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#if defined(POLARSSL_HAVE_IPV6) +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#include <ws2tcpip.h> +#endif + +#include <winsock2.h> +#include <windows.h> + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#if defined(POLARSSL_HAVE_TIME) +#include <sys/time.h> +#endif +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <netdb.h> +#include <errno.h> + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__DragonFly__) +#include <sys/endian.h> +#elif defined(__APPLE__) || defined(HAVE_MACHINE_ENDIAN_H) || \ + defined(EFIX64) || defined(EFI32) +#include <machine/endian.h> +#elif defined(sun) +#include <sys/isa_defs.h> +#elif defined(_AIX) || defined(HAVE_ARPA_NAMESER_COMPAT_H) +#include <arpa/nameser_compat.h> +#else +#include <endian.h> +#endif + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include <stdlib.h> +#include <stdio.h> + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#define snprintf _snprintf +#endif + +#if defined(POLARSSL_HAVE_TIME) +#include <time.h> +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +/* + * htons() is not always available. + * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and + * __BIG_ENDIAN to help determine endianness. + */ +#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN +#define POLARSSL_HTONS(n) (n) +#define POLARSSL_HTONL(n) (n) +#else +#define POLARSSL_HTONS(n) ((((unsigned short)(n) & 0xFF ) << 8 ) | \ + (((unsigned short)(n) & 0xFF00 ) >> 8 )) +#define POLARSSL_HTONL(n) ((((unsigned long )(n) & 0xFF ) << 24) | \ + (((unsigned long )(n) & 0xFF00 ) << 8 ) | \ + (((unsigned long )(n) & 0xFF0000 ) >> 8 ) | \ + (((unsigned long )(n) & 0xFF000000) >> 24)) +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_snprintf snprintf +#endif + +unsigned short net_htons( unsigned short n ); +unsigned long net_htonl( unsigned long n ); +#define net_htons(n) POLARSSL_HTONS(n) +#define net_htonl(n) POLARSSL_HTONL(n) + +/* + * 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( POLARSSL_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Initiate a TCP connection with host:port + */ +int net_connect( int *fd, const char *host, int port ) +{ +#if defined(POLARSSL_HAVE_IPV6) + int ret; + struct addrinfo hints, *addr_list, *cur; + char port_str[6]; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* getaddrinfo expects port as a string */ + memset( port_str, 0, sizeof( port_str ) ); + polarssl_snprintf( port_str, sizeof( port_str ), "%d", port ); + + /* Do name resolution with both IPv6 and IPv4, but only TCP */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 ) + return( POLARSSL_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = POLARSSL_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + *fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( *fd < 0 ) + { + ret = POLARSSL_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( *fd ); + ret = POLARSSL_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +#else + /* Legacy IPv4-only version */ + + int ret; + struct sockaddr_in server_addr; + struct hostent *server_host; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + if( ( server_host = gethostbyname( host ) ) == NULL ) + return( POLARSSL_ERR_NET_UNKNOWN_HOST ); + + if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) + return( POLARSSL_ERR_NET_SOCKET_FAILED ); + + memcpy( (void *) &server_addr.sin_addr, + (void *) server_host->h_addr, + server_host->h_length ); + + server_addr.sin_family = AF_INET; + server_addr.sin_port = net_htons( port ); + + if( connect( *fd, (struct sockaddr *) &server_addr, + sizeof( server_addr ) ) < 0 ) + { + close( *fd ); + return( POLARSSL_ERR_NET_CONNECT_FAILED ); + } + + return( 0 ); +#endif /* POLARSSL_HAVE_IPV6 */ +} + +/* + * Create a listening socket on bind_ip:port + */ +int net_bind( int *fd, const char *bind_ip, int port ) +{ +#if defined(POLARSSL_HAVE_IPV6) + int n, ret; + struct addrinfo hints, *addr_list, *cur; + char port_str[6]; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* getaddrinfo expects port as a string */ + memset( port_str, 0, sizeof( port_str ) ); + polarssl_snprintf( port_str, sizeof( port_str ), "%d", port ); + + /* Bind to IPv6 and/or IPv4, but only in TCP */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 ) + return( POLARSSL_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = POLARSSL_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + *fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( *fd < 0 ) + { + ret = POLARSSL_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( *fd ); + ret = POLARSSL_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 ) + { + close( *fd ); + ret = POLARSSL_ERR_NET_BIND_FAILED; + continue; + } + + if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 ) + { + close( *fd ); + ret = POLARSSL_ERR_NET_LISTEN_FAILED; + continue; + } + + /* I we ever get there, it's a success */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +#else + /* Legacy IPv4-only version */ + + int ret, n, c[4]; + struct sockaddr_in server_addr; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) + return( POLARSSL_ERR_NET_SOCKET_FAILED ); + + n = 1; + setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ); + + server_addr.sin_addr.s_addr = net_htonl( INADDR_ANY ); + server_addr.sin_family = AF_INET; + server_addr.sin_port = net_htons( port ); + + if( bind_ip != NULL ) + { + memset( c, 0, sizeof( c ) ); + sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] ); + + for( n = 0; n < 4; n++ ) + if( c[n] < 0 || c[n] > 255 ) + break; + + if( n == 4 ) + server_addr.sin_addr.s_addr = net_htonl( + ( (uint32_t) c[0] << 24 ) | + ( (uint32_t) c[1] << 16 ) | + ( (uint32_t) c[2] << 8 ) | + ( (uint32_t) c[3] ) ); + } + + if( bind( *fd, (struct sockaddr *) &server_addr, + sizeof( server_addr ) ) < 0 ) + { + close( *fd ); + return( POLARSSL_ERR_NET_BIND_FAILED ); + } + + if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 ) + { + close( *fd ); + return( POLARSSL_ERR_NET_LISTEN_FAILED ); + } + + return( 0 ); +#endif /* POLARSSL_HAVE_IPV6 */ +} + +#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( int fd ) +{ + ((void) fd); + 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( int fd ) +{ + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if( ( fcntl( 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 net_accept( int bind_fd, int *client_fd, void *client_ip ) +{ +#if defined(POLARSSL_HAVE_IPV6) + struct sockaddr_storage client_addr; +#else + struct sockaddr_in client_addr; +#endif + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) + socklen_t n = (socklen_t) sizeof( client_addr ); +#else + int n = (int) sizeof( client_addr ); +#endif + + *client_fd = (int) accept( bind_fd, (struct sockaddr *) + &client_addr, &n ); + + if( *client_fd < 0 ) + { + if( net_would_block( bind_fd ) != 0 ) + return( POLARSSL_ERR_NET_WANT_READ ); + + return( POLARSSL_ERR_NET_ACCEPT_FAILED ); + } + + if( client_ip != NULL ) + { +#if defined(POLARSSL_HAVE_IPV6) + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + memcpy( client_ip, &addr4->sin_addr.s_addr, + sizeof( addr4->sin_addr.s_addr ) ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + memcpy( client_ip, &addr6->sin6_addr.s6_addr, + sizeof( addr6->sin6_addr.s6_addr ) ); + } +#else + memcpy( client_ip, &client_addr.sin_addr.s_addr, + sizeof( client_addr.sin_addr.s_addr ) ); +#endif /* POLARSSL_HAVE_IPV6 */ + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int net_set_block( int fd ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( fd, FIONBIO, &n ) ); +#else + return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int net_set_nonblock( int fd ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( fd, FIONBIO, &n ) ); +#else + return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +#if defined(POLARSSL_HAVE_TIME) +/* + * Portable usleep helper + */ +void net_usleep( unsigned long usec ) +{ + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if !defined(_WIN32) && ( 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 /* POLARSSL_HAVE_TIME */ + +/* + * Read at most 'len' characters + */ +int net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int fd = *((int *) ctx); + int ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( fd ) != 0 ) + return( POLARSSL_ERR_NET_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( POLARSSL_ERR_NET_WANT_READ ); +#endif + + return( POLARSSL_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Write at most 'len' characters + */ +int net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int fd = *((int *) ctx); + int ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( fd ) != 0 ) + return( POLARSSL_ERR_NET_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( POLARSSL_ERR_NET_WANT_WRITE ); +#endif + + return( POLARSSL_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Gracefully close the connection + */ +void net_close( int fd ) +{ + shutdown( fd, 2 ); + close( fd ); +} + +#endif /* POLARSSL_NET_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/oid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/oid.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,693 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_OID_C) + +#include "polarssl/oid.h" +#include "polarssl/rsa.h" + +#include <stdio.h> +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_snprintf snprintf +#endif + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "polarssl/x509.h" +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, 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 asn1_buf *oid ) \ +{ \ + const TYPE_T *p = LIST; \ + const oid_descriptor_t *cur = (const 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 oid_descriptor_t *) p; \ + } \ + return( NULL ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * 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 asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( POLARSSL_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 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( POLARSSL_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a 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( POLARSSL_ERR_OID_NOT_FOUND ); \ +} + +/* + * For X520 attribute types + */ +typedef struct { + oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( 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(oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name); + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +/* + * For X509 extensions + */ +typedef struct { + oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + EXT_KEY_USAGE, + }, + { + { ADD_LEN( OID_EXTENDED_KEY_USAGE ), "id-ce-keyUsage", "Extended Key Usage" }, + EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + 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(oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type); + +static const oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_descriptor_t, ext_key_usage, oid_ext_key_usage); +FN_OID_GET_ATTR1(oid_get_extended_key_usage, oid_descriptor_t, ext_key_usage, const char *, description); +#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */ + +#if defined(POLARSSL_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + oid_descriptor_t descriptor; + md_type_t md_alg; + pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ + { + { ADD_LEN( OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + POLARSSL_MD_MD2, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + POLARSSL_MD_MD4, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + POLARSSL_MD_MD5, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + POLARSSL_MD_SHA1, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + POLARSSL_MD_SHA224, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + POLARSSL_MD_SHA256, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + POLARSSL_MD_SHA384, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + POLARSSL_MD_SHA512, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + POLARSSL_MD_SHA1, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + POLARSSL_MD_SHA1, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + POLARSSL_MD_SHA224, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + POLARSSL_MD_SHA256, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + POLARSSL_MD_SHA384, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + POLARSSL_MD_SHA512, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + POLARSSL_MD_NONE, POLARSSL_PK_RSASSA_PSS, + }, + { + { NULL, 0, NULL, NULL }, + POLARSSL_MD_NONE, POLARSSL_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg); +FN_OID_GET_DESCRIPTOR_ATTR1(oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description); +FN_OID_GET_ATTR2(oid_get_sig_alg, oid_sig_alg_t, sig_alg, md_type_t, md_alg, pk_type_t, pk_alg); +FN_OID_GET_OID_BY_ATTR2(oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, pk_type_t, pk_alg, md_type_t, md_alg); +#endif /* POLARSSL_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + oid_descriptor_t descriptor; + pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + POLARSSL_PK_ECKEY, + }, + { + { ADD_LEN( OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + POLARSSL_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + POLARSSL_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg); +FN_OID_GET_ATTR1(oid_get_pk_alg, oid_pk_alg_t, pk_alg, pk_type_t, pk_alg); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, pk_type_t, pk_alg); + +#if defined(POLARSSL_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + oid_descriptor_t descriptor; + ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ + { + { ADD_LEN( OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + POLARSSL_ECP_DP_SECP192R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + POLARSSL_ECP_DP_SECP224R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + POLARSSL_ECP_DP_SECP256R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + POLARSSL_ECP_DP_SECP384R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + POLARSSL_ECP_DP_SECP521R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + POLARSSL_ECP_DP_SECP192K1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + POLARSSL_ECP_DP_SECP224K1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + POLARSSL_ECP_DP_SECP256K1, + }, + { + { ADD_LEN( OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + POLARSSL_ECP_DP_BP256R1, + }, + { + { ADD_LEN( OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + POLARSSL_ECP_DP_BP384R1, + }, + { + { ADD_LEN( OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + POLARSSL_ECP_DP_BP512R1, + }, + { + { NULL, 0, NULL, NULL }, + POLARSSL_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp); +FN_OID_GET_ATTR1(oid_get_ec_grp, oid_ecp_grp_t, grp_id, ecp_group_id, grp_id); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, ecp_group_id, grp_id); +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + oid_descriptor_t descriptor; + cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( OID_DES_CBC ), "desCBC", "DES-CBC" }, + POLARSSL_CIPHER_DES_CBC, + }, + { + { ADD_LEN( OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + POLARSSL_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + POLARSSL_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg); +FN_OID_GET_ATTR1(oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, cipher_type_t, cipher_alg); +#endif /* POLARSSL_CIPHER_C */ + +#if defined(POLARSSL_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + oid_descriptor_t descriptor; + md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ + { + { ADD_LEN( OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + POLARSSL_MD_MD2, + }, + { + { ADD_LEN( OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + POLARSSL_MD_MD4, + }, + { + { ADD_LEN( OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + POLARSSL_MD_MD5, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + POLARSSL_MD_SHA1, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + POLARSSL_MD_SHA224, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + POLARSSL_MD_SHA256, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + POLARSSL_MD_SHA384, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + POLARSSL_MD_SHA512, + }, + { + { NULL, 0, NULL, NULL }, + POLARSSL_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg); +FN_OID_GET_ATTR1(oid_get_md_alg, oid_md_alg_t, md_alg, md_type_t, md_alg); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, md_type_t, md_alg); +#endif /* POLARSSL_MD_C */ + +#if defined(POLARSSL_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + oid_descriptor_t descriptor; + md_type_t md_alg; + cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + POLARSSL_MD_SHA1, POLARSSL_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + POLARSSL_MD_SHA1, POLARSSL_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + POLARSSL_MD_NONE, POLARSSL_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg); +FN_OID_GET_ATTR2(oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, md_type_t, md_alg, cipher_type_t, cipher_alg); +#endif /* POLARSSL_PKCS12_C */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include <stdarg.h> + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( POLARSSL_ERR_OID_BUF_TOO_SMALL ); \ + \ + if( (unsigned int) ret >= n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_OID_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +/* Return the x.y.z.... style numeric string for the given OID */ +int oid_get_numeric_string( char *buf, size_t size, + const 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 = polarssl_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + SAFE_SNPRINTF(); + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( POLARSSL_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = polarssl_snprintf( p, n, ".%d", value ); + SAFE_SNPRINTF(); + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* POLARSSL_OID_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/padlock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/padlock.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,168 @@ +/* + * VIA PadLock support functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PADLOCK_C) + +#include "polarssl/padlock.h" + +#include <string.h> + +#if defined(POLARSSL_HAVE_X86) + +/* + * PadLock detection routine + */ +int padlock_supports( 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 padlock_xcryptecb( 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 = 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 padlock_xcryptcbc( 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( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = 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 /* POLARSSL_HAVE_X86 */ + +#endif /* POLARSSL_PADLOCK_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pbkdf2.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pbkdf2.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,65 @@ +/** + * \file pbkdf2.c + * + * \brief Compatibility wrappers for pkcs5.c + * + * \author Mathias Olsson <mathias@kompetensum.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * PBKDF2 is part of PKCS#5 + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PBKDF2_C) + +#include "polarssl/pbkdf2.h" +#include "polarssl/pkcs5.h" + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +int pbkdf2_hmac( 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 ) +{ + return pkcs5_pbkdf2_hmac( ctx, password, plen, salt, slen, iteration_count, + key_length, output ); +} +#endif + +#if defined(POLARSSL_SELF_TEST) +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +int pbkdf2_self_test( int verbose ) +{ + return pkcs5_self_test( verbose ); +} +#endif +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_PBKDF2_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pem.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,445 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C) + +#include "polarssl/pem.h" +#include "polarssl/base64.h" +#include "polarssl/des.h" +#include "polarssl/aes.h" +#include "polarssl/md5.h" +#include "polarssl/cipher.h" + +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_PEM_PARSE_C) +void pem_init( pem_context *ctx ) +{ + memset( ctx, 0, sizeof( pem_context ) ); +} + +#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_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( POLARSSL_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 ) +{ + md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + + md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + md5_starts( &md5_ctx ); + md5_update( &md5_ctx, pwd, pwdlen ); + md5_update( &md5_ctx, iv, 8 ); + md5_finish( &md5_ctx, md5sum ); + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + + md5_free( &md5_ctx ); + polarssl_zeroize( md5sum, 16 ); + return; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + md5_starts( &md5_ctx ); + md5_update( &md5_ctx, md5sum, 16 ); + md5_update( &md5_ctx, pwd, pwdlen ); + md5_update( &md5_ctx, iv, 8 ); + md5_finish( &md5_ctx, md5sum ); + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + + md5_free( &md5_ctx ); + polarssl_zeroize( md5sum, 16 ); +} + +#if defined(POLARSSL_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 ) +{ + des_context des_ctx; + unsigned char des_key[8]; + + des_init( &des_ctx ); + + pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); + + des_setkey_dec( &des_ctx, des_key ); + des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen, + des_iv, buf, buf ); + + des_free( &des_ctx ); + polarssl_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 ) +{ + des3_context des3_ctx; + unsigned char des3_key[24]; + + des3_init( &des3_ctx ); + + pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); + + des3_set3key_dec( &des3_ctx, des3_key ); + des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen, + des3_iv, buf, buf ); + + des3_free( &des3_ctx ); + polarssl_zeroize( des3_key, 24 ); +} +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_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 ) +{ + aes_context aes_ctx; + unsigned char aes_key[32]; + + aes_init( &aes_ctx ); + + pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); + + aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); + aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen, + aes_iv, buf, buf ); + + aes_free( &aes_ctx ); + polarssl_zeroize( aes_key, keylen ); +} +#endif /* POLARSSL_AES_C */ + +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + +int pem_read_buffer( 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(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) + unsigned char pem_iv[16]; + cipher_type_t enc_alg = POLARSSL_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + + if( ctx == NULL ) + return( POLARSSL_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + 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(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( POLARSSL_ERR_PEM_INVALID_DATA ); + + +#if defined(POLARSSL_DES_C) + if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = POLARSSL_CIPHER_DES_CBC; + + s1 += 18; + if( pem_get_iv( s1, pem_iv, 8) != 0 ) + return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_AES_C) + if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = POLARSSL_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = POLARSSL_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = POLARSSL_CIPHER_AES_256_CBC; + else + return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* POLARSSL_AES_C */ + + if( enc_alg == POLARSSL_CIPHER_NONE ) + return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( POLARSSL_ERR_PEM_INVALID_DATA ); +#else + return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + } + + len = 0; + ret = base64_decode( NULL, &len, s1, s2 - s1 ); + + if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER ) + return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = polarssl_malloc( len ) ) == NULL ) + return( POLARSSL_ERR_PEM_MALLOC_FAILED ); + + if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 ) + { + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); + } + + if( enc != 0 ) + { +#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) + if( pwd == NULL ) + { + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED ); + } + +#if defined(POLARSSL_DES_C) + if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC ) + pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == POLARSSL_CIPHER_DES_CBC ) + pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_AES_C) + if( enc_alg == POLARSSL_CIPHER_AES_128_CBC ) + pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC ) + pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC ) + pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* POLARSSL_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 ) + { + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void pem_free( pem_context *ctx ) +{ + polarssl_free( ctx->buf ); + polarssl_free( ctx->info ); + + polarssl_zeroize( ctx, sizeof( pem_context ) ); +} +#endif /* POLARSSL_PEM_PARSE_C */ + +#if defined(POLARSSL_PEM_WRITE_C) +int 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 = 0, add_len = 0; + + base64_encode( NULL, &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( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( ( encode_buf = polarssl_malloc( use_len ) ) == NULL ) + return( POLARSSL_ERR_PEM_MALLOC_FAILED ); + + if( ( ret = base64_encode( encode_buf, &use_len, der_data, + der_len ) ) != 0 ) + { + polarssl_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; + + polarssl_free( encode_buf ); + return( 0 ); +} +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pk.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pk.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,374 @@ +/* + * Public Key abstraction layer + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_C) +#include "polarssl/pk.h" +#include "polarssl/pk_wrap.h" + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Initialise a pk_context + */ +void pk_init( pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a pk_context + */ +void pk_free( pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return; + + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + polarssl_zeroize( ctx, sizeof( pk_context ) ); +} + +/* + * Get pk_info structure from type + */ +const pk_info_t * pk_info_from_type( pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(POLARSSL_RSA_C) + case POLARSSL_PK_RSA: + return( &rsa_info ); +#endif +#if defined(POLARSSL_ECP_C) + case POLARSSL_PK_ECKEY: + return( &eckey_info ); + case POLARSSL_PK_ECKEY_DH: + return( &eckeydh_info ); +#endif +#if defined(POLARSSL_ECDSA_C) + case POLARSSL_PK_ECDSA: + return( &ecdsa_info ); +#endif + /* POLARSSL_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int pk_init_ctx( pk_context *ctx, const pk_info_t *info ) +{ + if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +/* + * Initialize an RSA-alt context + */ +int pk_init_ctx_rsa_alt( pk_context *ctx, void * key, + pk_rsa_alt_decrypt_func decrypt_func, + pk_rsa_alt_sign_func sign_func, + pk_rsa_alt_key_len_func key_len_func ) +{ + rsa_alt_context *rsa_alt; + const pk_info_t *info = &rsa_alt_info; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (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 ); +} + +/* + * Tell if a PK can do the operations of the given type + */ +int pk_can_do( pk_context *ctx, 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 pk_sign and pk_verify + */ +static inline int pk_hashlen_helper( md_type_t md_alg, size_t *hash_len ) +{ + const md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = md_info->size; + return( 0 ); +} + +/* + * Verify a signature + */ +int pk_verify( pk_context *ctx, 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( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->verify_func == NULL ) + return( POLARSSL_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 pk_verify_ext( pk_type_t type, const void *options, + pk_context *ctx, 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( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ! pk_can_do( ctx, type ) ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + if( type == POLARSSL_PK_RSASSA_PSS ) + { +#if defined(POLARSSL_RSA_C) && defined(POLARSSL_PKCS1_V21) + int ret; + const pk_rsassa_pss_options *pss_opts; + + if( options == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const pk_rsassa_pss_options *) options; + + if( sig_len < pk_get_len( ctx ) ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + ret = rsa_rsassa_pss_verify_ext( pk_rsa( *ctx ), + NULL, NULL, 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 > pk_get_len( ctx ) ) + return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); +#endif + } + + /* General case: no options */ + if( options != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + return( pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature + */ +int pk_sign( pk_context *ctx, 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( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->sign_func == NULL ) + return( POLARSSL_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 pk_decrypt( 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( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( POLARSSL_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 pk_encrypt( 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( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( POLARSSL_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 pk_check_pair( const pk_context *pub, const pk_context *prv ) +{ + if( pub == NULL || pub->pk_info == NULL || + prv == NULL || prv->pk_info == NULL || + prv->pk_info->check_pair_func == NULL ) + { + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->type == POLARSSL_PK_RSA_ALT ) + { + if( pub->pk_info->type != POLARSSL_PK_RSA ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t pk_get_size( const pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_size( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int pk_debug( const pk_context *ctx, pk_debug_item *items ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char * pk_get_name( const pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +pk_type_t pk_get_type( const pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#endif /* POLARSSL_PK_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pk_wrap.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pk_wrap.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,503 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_C) +#include "polarssl/pk_wrap.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "polarssl/rsa.h" + +#include <string.h> + +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_RSA_C) +static int rsa_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_RSA || + type == POLARSSL_PK_RSASSA_PSS ); +} + +static size_t rsa_get_size( const void *ctx ) +{ + return( 8 * ((const rsa_context *) ctx)->len ); +} + +static int rsa_verify_wrap( void *ctx, 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 < ((rsa_context *) ctx)->len ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = rsa_pkcs1_verify( (rsa_context *) ctx, NULL, NULL, + RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + if( sig_len > ((rsa_context *) ctx)->len ) + return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, 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 = ((rsa_context *) ctx)->len; + + return( rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, 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 != ((rsa_context *) ctx)->len ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_pkcs1_decrypt( (rsa_context *) ctx, f_rng, p_rng, + 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 = ((rsa_context *) ctx)->len; + + if( *olen > osize ) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( rsa_pkcs1_encrypt( (rsa_context *) ctx, + f_rng, p_rng, RSA_PUBLIC, ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( rsa_check_pub_priv( (const rsa_context *) pub, + (const rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( rsa_context ) ); + + if( ctx != NULL ) + rsa_init( (rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + rsa_free( (rsa_context *) ctx ); + polarssl_free( ctx ); +} + +static void rsa_debug( const void *ctx, pk_debug_item *items ) +{ + items->type = POLARSSL_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((rsa_context *) ctx)->N ); + + items++; + + items->type = POLARSSL_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((rsa_context *) ctx)->E ); +} + +const pk_info_t rsa_info = { + POLARSSL_PK_RSA, + "RSA", + rsa_get_size, + 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 /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_ECKEY || + type == POLARSSL_PK_ECKEY_DH || + type == POLARSSL_PK_ECDSA ); +} + +static size_t eckey_get_size( const void *ctx ) +{ + return( ((ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(POLARSSL_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, 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, 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, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ecdsa_context ecdsa; + + ecdsa_init( &ecdsa ); + + if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, 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; + ecdsa_context ecdsa; + + ecdsa_init( &ecdsa ); + + if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + ecdsa_free( &ecdsa ); + + return( ret ); +} + +#endif /* POLARSSL_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( ecp_check_pub_priv( (const ecp_keypair *) pub, + (const ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( ecp_keypair ) ); + + if( ctx != NULL ) + ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + ecp_keypair_free( (ecp_keypair *) ctx ); + polarssl_free( ctx ); +} + +static void eckey_debug( const void *ctx, pk_debug_item *items ) +{ + items->type = POLARSSL_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((ecp_keypair *) ctx)->Q ); +} + +const pk_info_t eckey_info = { + POLARSSL_PK_ECKEY, + "EC", + eckey_get_size, + eckey_can_do, +#if defined(POLARSSL_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( pk_type_t type ) +{ + return( type == POLARSSL_PK_ECKEY || + type == POLARSSL_PK_ECKEY_DH ); +} + +const pk_info_t eckeydh_info = { + POLARSSL_PK_ECKEY_DH, + "EC_DH", + eckey_get_size, /* 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 /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_ECDSA_C) +static int ecdsa_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, 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 = ecdsa_read_signature( (ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == POLARSSL_ERR_ECP_SIG_LEN_MISMATCH ) + return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( void *ctx, 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 ) +{ + /* Use deterministic ECDSA by default if available */ +#if defined(POLARSSL_ECDSA_DETERMINISTIC) + ((void) f_rng); + ((void) p_rng); + + return( ecdsa_write_signature_det( (ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, md_alg ) ); +#else + ((void) md_alg); + + return( ecdsa_write_signature( (ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ +} + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( ecdsa_context ) ); + + if( ctx != NULL ) + ecdsa_init( (ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + ecdsa_free( (ecdsa_context *) ctx ); + polarssl_free( ctx ); +} + +const pk_info_t ecdsa_info = { + POLARSSL_PK_ECDSA, + "ECDSA", + eckey_get_size, /* 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 /* POLARSSL_ECDSA_C */ + +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_RSA ); +} + +static size_t rsa_alt_get_size( const void *ctx ) +{ + const rsa_alt_context *rsa_alt = (const rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, 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 ) +{ + rsa_alt_context *rsa_alt = (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, 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 ) +{ + rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(POLARSSL_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[POLARSSL_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret; + + if( rsa_alt_get_size( prv ) != rsa_get_size( pub ) ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, POLARSSL_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, POLARSSL_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* POLARSSL_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( rsa_alt_context ) ); + polarssl_free( ctx ); +} + +const pk_info_t rsa_alt_info = { + POLARSSL_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_size, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, + rsa_alt_decrypt_wrap, + NULL, +#if defined(POLARSSL_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, + NULL, +}; + +#endif /* POLARSSL_PK_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pkcs11.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pkcs11.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,235 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong <dejong@fox-it.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "polarssl/pkcs11.h" + +#if defined(POLARSSL_PKCS11_C) + +#include "polarssl/md.h" +#include "polarssl/oid.h" +#include "polarssl/x509_crt.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +int pkcs11_x509_cert_init( 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 = polarssl_malloc( 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 != x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + polarssl_free( cert_blob ); + + return( ret ); +} + + +int pkcs11_priv_key_init( pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + x509_crt cert; + + x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + x509_crt_free( &cert ); + + return( ret ); +} + +void pkcs11_priv_key_free( pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int pkcs11_decrypt( 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( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( RSA_PRIVATE != mode ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( POLARSSL_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( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int pkcs11_sign( pkcs11_context *ctx, + int mode, + 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( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( RSA_PRIVATE != mode ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != POLARSSL_MD_NONE ) + { + const md_info_t *md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = 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( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != POLARSSL_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = ASN1_NULL; + *p++ = 0x00; + *p++ = 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( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(POLARSSL_PKCS11_C) */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pkcs12.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pkcs12.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,360 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PKCS12_C) + +#include "polarssl/pkcs12.h" +#include "polarssl/asn1.h" +#include "polarssl/cipher.h" + +#include <string.h> + +#if defined(POLARSSL_ARC4_C) +#include "polarssl/arc4.h" +#endif + +#if defined(POLARSSL_DES_C) +#include "polarssl/des.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static int pkcs12_parse_pbe_params( asn1_buf *params, + 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 != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + if( *p != end ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, 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; + asn1_buf salt; + size_t i; + unsigned char unipwd[258]; + + memset( &salt, 0, sizeof(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 = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +int pkcs12_pbe_sha1_rc4_128( 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(POLARSSL_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret; + unsigned char key[16]; + arc4_context ctx; + ((void) mode); + + arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + arc4_setup( &ctx, key, 16 ); + if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + polarssl_zeroize( key, sizeof( key ) ); + arc4_free( &ctx ); + + return( ret ); +#endif /* POLARSSL_ARC4_C */ +} + +int pkcs12_pbe( asn1_buf *pbe_params, int mode, + cipher_type_t cipher_type, 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 cipher_info_t *cipher_info; + cipher_context_t cipher_ctx; + size_t olen = 0; + + cipher_info = cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_length / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + cipher_init( &cipher_ctx ); + + if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, (operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + polarssl_zeroize( key, sizeof( key ) ); + polarssl_zeroize( iv, sizeof( iv ) ); + 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 pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + 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[POLARSSL_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + + size_t hlen, use_len, v, i; + + const md_info_t *md_info; + 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( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA ); + + md_info = md_info_from_type( md_type ); + if( md_info == NULL ) + return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + md_init( &md_ctx ); + + if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) + return( ret ); + hlen = 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 = md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 ) + goto exit; + + if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 ) + goto exit; + + if( ( ret = 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 = 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: + polarssl_zeroize( salt_block, sizeof( salt_block ) ); + polarssl_zeroize( pwd_block, sizeof( pwd_block ) ); + polarssl_zeroize( hash_block, sizeof( hash_block ) ); + polarssl_zeroize( hash_output, sizeof( hash_output ) ); + + md_free( &md_ctx ); + + return( ret ); +} + +#endif /* POLARSSL_PKCS12_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pkcs5.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pkcs5.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,407 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson <mathias@kompetensum.com> + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PKCS5_C) + +#include "polarssl/pkcs5.h" +#include "polarssl/asn1.h" +#include "polarssl/cipher.h" +#include "polarssl/oid.h" + +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif + +static int pkcs5_parse_pbkdf2_params( const asn1_buf *params, + asn1_buf *salt, int *iterations, + int *keylen, md_type_t *md_type ) +{ + int ret; + asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = asn1_get_tag( &p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + salt->p = p; + p += salt->len; + + if( ( ret = asn1_get_int( &p, end, iterations ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( p == end ) + return( 0 ); + + if( ( ret = asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( !OID_CMP( OID_HMAC_SHA1, &prf_alg_oid ) ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + *md_type = POLARSSL_MD_SHA1; + + if( p != end ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int pkcs5_pbes2( 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; + asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + asn1_buf salt; + md_type_t md_type = POLARSSL_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const md_info_t *md_info; + const cipher_info_t *cipher_info; + md_context_t md_ctx; + cipher_type_t cipher_alg; + 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 != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + // Only PBKDF2 supported at the moment + // + if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = md_info_from_type( md_type ); + if( md_info == NULL ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( POLARSSL_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_length / 8; + + if( enc_scheme_params.tag != ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT ); + } + + md_init( &md_ctx ); + cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) + goto exit; + + if( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, (operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + md_free( &md_ctx ); + cipher_free( &cipher_ctx ); + + return( ret ); +} + +int pkcs5_pbkdf2_hmac( 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[POLARSSL_MD_MAX_SIZE]; + unsigned char work[POLARSSL_MD_MAX_SIZE]; + unsigned char md_size = 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( POLARSSL_ERR_PKCS5_BAD_INPUT_DATA ); + + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_update( ctx, salt, slen ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_update( ctx, counter, 4 ) ) != 0 ) + return( ret ); + + if( ( ret = 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 = md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_update( ctx, md1, md_size ) ) != 0 ) + return( ret ); + + if( ( ret = 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(POLARSSL_SELF_TEST) + +#if !defined(POLARSSL_SHA1_C) +int pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + polarssl_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 pkcs5_self_test( int verbose ) +{ + md_context_t sha1_ctx; + const md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + md_init( &sha1_ctx ); + + info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = 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 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + polarssl_printf( "\n" ); + +exit: + md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* POLARSSL_SHA1_C */ + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_PKCS5_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pkparse.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pkparse.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1265 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_PARSE_C) + +#include "polarssl/pk.h" +#include "polarssl/asn1.h" +#include "polarssl/oid.h" + +#include <string.h> + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif +#if defined(POLARSSL_PKCS5_C) +#include "polarssl/pkcs5.h" +#endif +#if defined(POLARSSL_PKCS12_C) +#include "polarssl/pkcs12.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(POLARSSL_FS_IO) +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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. + */ +int pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( POLARSSL_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = polarssl_malloc( *n + 1 ) ) == NULL ) + { + fclose( f ); + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + polarssl_free( *buf ); + return( POLARSSL_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int pk_parse_keyfile( pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int pk_parse_public_keyfile( pk_context *ctx, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = pk_parse_public_key( ctx, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_ECP_C) +/* Minimally parse an ECParameters buffer to and asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + asn1_buf *params ) +{ + int ret; + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != ASN1_OID +#if defined(POLARSSL_PK_PARSE_EC_EXTENDED) + && params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) +#endif + ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(POLARSSL_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 asn1_buf *params, 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 = asn1_get_int( &p, end, &ver ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( POLARSSL_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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | 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 = asn1_get_tag( &p, end_field, &len, ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != OID_SIZE( OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mpi_msb( &grp->P ); + + if( p != end_field ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || + ( ret = mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || + ( ret = mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = 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 != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mpi_size( &grp->P ) + 1 || + mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mpi_msb( &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 ecp_group *grp, ecp_group_id *grp_id ) +{ + int ret = 0; + ecp_group ref; + const ecp_group_id *id; + + ecp_group_init( &ref ); + + for( id = ecp_grp_id_list(); *id != POLARSSL_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + ecp_group_free( &ref ); + MPI_CHK( ecp_use_known_dp( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mpi_get_bit( &grp->G.Y, 0 ) == mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == POLARSSL_ECP_DP_NONE ) + ret = POLARSSL_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 asn1_buf *params, + ecp_group_id *grp_id ) +{ + int ret; + ecp_group grp; + + 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: + ecp_group_free( &grp ); + + return( ret ); +} +#endif /* POLARSSL_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 asn1_buf *params, ecp_group *grp ) +{ + int ret; + ecp_group_id grp_id; + + if( params->tag == ASN1_OID ) + { + if( oid_get_ec_grp( params, &grp_id ) != 0 ) + return( POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(POLARSSL_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != POLARSSL_ECP_DP_NONE && grp->id != grp_id ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = ecp_use_known_dp( 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 ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + ecp_keypair *key ) +{ + int ret; + + if( ( ret = ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + rsa_context *rsa ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = asn1_get_mpi( p, end, &rsa->N ) ) != 0 || + ( ret = asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p != end ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = rsa_check_pubkey( rsa ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY ); + + rsa->len = mpi_size( &rsa->N ); + + return( 0 ); +} +#endif /* POLARSSL_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, + pk_type_t *pk_alg, asn1_buf *params ) +{ + int ret; + asn1_buf alg_oid; + + memset( params, 0, sizeof(asn1_buf) ); + + if( ( ret = asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_ALG + ret ); + + if( oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == POLARSSL_PK_RSA && + ( ( params->tag != ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( POLARSSL_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + pk_context *pk ) +{ + int ret; + size_t len; + asn1_buf alg_params; + pk_type_t pk_alg = POLARSSL_PK_NONE; + const pk_info_t *pk_info; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_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 = asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(POLARSSL_RSA_C) + if( pk_alg == POLARSSL_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, pk_rsa( *pk ) ); + } else +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) + if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, pk_ec( *pk ) ); + } else +#endif /* POLARSSL_ECP_C */ + ret = POLARSSL_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + pk_free( pk ); + + return( ret ); +} + +#if defined(POLARSSL_RSA_C) +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( 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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( rsa->ver != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_VERSION ); + } + + if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) + { + rsa_free( rsa ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + rsa->len = mpi_size( &rsa->N ); + + if( p != end ) + { + rsa_free( rsa ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + if( ( ret = rsa_check_privkey( rsa ) ) != 0 ) + { + rsa_free( rsa ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version, pubkey_done; + size_t len; + 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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( POLARSSL_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_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 = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_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 != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( ! pubkey_done && + ( ret = ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + */ +static int pk_parse_key_pkcs8_unencrypted_der( + pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + pk_type_t pk_alg = POLARSSL_PK_NONE; + const 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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(POLARSSL_RSA_C) + if( pk_alg == POLARSSL_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 ) + { + pk_free( pk ); + return( ret ); + } + } else +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) + if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), p, len ) ) != 0 ) + { + pk_free( pk ); + return( ret ); + } + } else +#endif /* POLARSSL_ECP_C */ + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + */ +#if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + 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; + asn1_buf pbe_alg_oid, pbe_params; +#if defined(POLARSSL_PKCS12_C) + cipher_type_t cipher_alg; + md_type_t md_alg; +#endif + + memset( buf, 0, sizeof( buf ) ); + + p = (unsigned char *) key; + end = p + keylen; + + if( pwdlen == 0 ) + return( POLARSSL_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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len > sizeof( buf ) ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + /* + * Decrypt EncryptedData with appropriate PDE + */ +#if defined(POLARSSL_PKCS12_C) + if( oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = pkcs12_pbe( &pbe_params, PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( OID_CMP( OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) ) + { + if( ( ret = pkcs12_pbe_sha1_rc4_128( &pbe_params, + PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not ASN1_CONSTRUCTED | ASN1_SEQUENCE + // + if( *buf != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* POLARSSL_PKCS12_C */ +#if defined(POLARSSL_PKCS5_C) + if( OID_CMP( OID_PKCS5_PBES2, &pbe_alg_oid ) ) + { + if( ( ret = pkcs5_pbes2( &pbe_params, PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* POLARSSL_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */ + +/* + * Parse a private key + */ +int pk_parse_key( pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + const pk_info_t *pk_info; + +#if defined(POLARSSL_PEM_PARSE_C) + size_t len; + pem_context pem; + + pem_init( &pem ); + +#if defined(POLARSSL_RSA_C) + ret = pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) + return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) + ret = pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) + return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* POLARSSL_ECP_C */ + + ret = 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 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C) + ret = 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 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* POLARSSL_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(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C) + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, + pwd, pwdlen ) ) == 0 ) + { + return( 0 ); + } + + pk_free( pk ); + + if( ret == POLARSSL_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */ + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + pk_free( pk ); + +#if defined(POLARSSL_RSA_C) + if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + pk_free( pk ); +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) + if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + pk_free( pk ); +#endif /* POLARSSL_ECP_C */ + + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int pk_parse_public_key( pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char *p; +#if defined(POLARSSL_PEM_PARSE_C) + size_t len; + pem_context pem; + + pem_init( &pem ); + ret = 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 != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } +#endif /* POLARSSL_PEM_PARSE_C */ + p = (unsigned char *) key; + + ret = pk_parse_subpubkey( &p, p + keylen, ctx ); + +#if defined(POLARSSL_PEM_PARSE_C) + pem_free( &pem ); +#endif + + return( ret ); +} + +#endif /* POLARSSL_PK_PARSE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/pkwrite.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/pkwrite.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,441 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_WRITE_C) + +#include "polarssl/pk.h" +#include "polarssl/asn1write.h" +#include "polarssl/oid.h" + +#include <string.h> + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif +#if defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(POLARSSL_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + rsa_context *rsa ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[POLARSSL_ECP_MAX_PT_LEN]; + + if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q, + POLARSSL_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p - start < (int) len ) + return( POLARSSL_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, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} +#endif /* POLARSSL_ECP_C */ + +int pk_write_pubkey( unsigned char **p, unsigned char *start, + const pk_context *key ) +{ + int ret; + size_t len = 0; + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, pk_rsa( *key ) ) ); + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, pk_ec( *key ) ) ); + else +#endif + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int pk_write_pubkey_der( 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; + + ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); + + if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ), + &oid, &oid_len ) ) != 0 ) + { + return( ret ); + } + +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, pk_ec( *key ) ) ); + } +#endif + + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c = buf + size; + size_t len = 0; + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + { + rsa_context *rsa = pk_rsa( *key ); + + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + } + else +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + ecp_keypair *ec = 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 */ + ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); + ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); + + ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); + ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) ); + ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey: write as MPI then fix tag */ + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) ); + *c = ASN1_OCTET_STRING; + + /* version */ + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + } + else +#endif /* POLARSSL_ECP_C */ + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(POLARSSL_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(POLARSSL_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 * POLARSSL_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 POLARSSL_MPI_MAX_SIZE / 2 + \ + POLARSSL_MPI_MAX_SIZE % 2 +#define RSA_PRV_DER_MAX_BYTES 47 + 3 * POLARSSL_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 + +#else /* POLARSSL_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_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 * POLARSSL_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 * POLARSSL_ECP_MAX_BYTES + +#else /* POLARSSL_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* POLARSSL_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 pk_write_pubkey_pem( 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 = pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = 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 pk_write_key_pem( 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 = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_PEM_WRITE_C */ + +#endif /* POLARSSL_PK_WRITE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/platform.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/platform.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,166 @@ +/* + * Platform abstraction layer + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PLATFORM_C) + +#include "polarssl/platform.h" + +#if defined(POLARSSL_PLATFORM_MEMORY) +#if !defined(POLARSSL_PLATFORM_STD_MALLOC) +static void *platform_malloc_uninit( size_t len ) +{ + ((void) len); + return( NULL ); +} + +#define POLARSSL_PLATFORM_STD_MALLOC platform_malloc_uninit +#endif /* !POLARSSL_PLATFORM_STD_MALLOC */ + +#if !defined(POLARSSL_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define POLARSSL_PLATFORM_STD_FREE platform_free_uninit +#endif /* !POLARSSL_PLATFORM_STD_FREE */ + +void * (*polarssl_malloc)( size_t ) = POLARSSL_PLATFORM_STD_MALLOC; +void (*polarssl_free)( void * ) = POLARSSL_PLATFORM_STD_FREE; + +int platform_set_malloc_free( void * (*malloc_func)( size_t ), + void (*free_func)( void * ) ) +{ + polarssl_malloc = malloc_func; + polarssl_free = free_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_MEMORY */ + +#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT) +#if !defined(POLARSSL_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 POLARSSL_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !POLARSSL_PLATFORM_STD_SNPRINTF */ + +int (*polarssl_snprintf)( char * s, size_t n, + const char * format, + ... ) = POLARSSL_PLATFORM_STD_SNPRINTF; + +int platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + polarssl_snprintf = snprintf_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_SNPRINTF_ALT */ + +#if defined(POLARSSL_PLATFORM_PRINTF_ALT) +#if !defined(POLARSSL_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define POLARSSL_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !POLARSSL_PLATFORM_STD_PRINTF */ + +int (*polarssl_printf)( const char *, ... ) = POLARSSL_PLATFORM_STD_PRINTF; + +int platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + polarssl_printf = printf_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_PRINTF_ALT */ + +#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) +#if !defined(POLARSSL_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 POLARSSL_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !POLARSSL_PLATFORM_STD_FPRINTF */ + +int (*polarssl_fprintf)( FILE *, const char *, ... ) = + POLARSSL_PLATFORM_STD_FPRINTF; + +int platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + polarssl_fprintf = fprintf_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */ + +#if defined(POLARSSL_PLATFORM_EXIT_ALT) +#if !defined(POLARSSL_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define POLARSSL_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !POLARSSL_PLATFORM_STD_EXIT */ + +void (*polarssl_exit)( int status ) = POLARSSL_PLATFORM_STD_EXIT; + +int platform_set_exit( void (*exit_func)( int status ) ) +{ + polarssl_exit = exit_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_EXIT_ALT */ + +#endif /* POLARSSL_PLATFORM_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ripemd160.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ripemd160.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,652 @@ +/* + * RIPE MD-160 implementation + * + * Copyright (C) 2014-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_RIPEMD160_C) + +#include "polarssl/ripemd160.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_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 polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void ripemd160_init( ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( ripemd160_context ) ); +} + +void ripemd160_free( ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( ripemd160_context ) ); +} + +/* + * RIPEMD-160 context setup + */ +void ripemd160_starts( 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; +} + +/* + * Process one block + */ +void ripemd160_process( 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; +} + +/* + * RIPEMD-160 process buffer + */ +void ripemd160_update( 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 ); + ripemd160_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + 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 ripemd160_finish( 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 ); + + ripemd160_update( ctx, ripemd160_padding, padn ); + 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 ripemd160( const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + ripemd160_context ctx; + + ripemd160_init( &ctx ); + ripemd160_starts( &ctx ); + ripemd160_update( &ctx, input, ilen ); + ripemd160_finish( &ctx, output ); + ripemd160_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = RIPEMD-160( file contents ) + */ +int ripemd160_file( const char *path, unsigned char output[20] ) +{ + FILE *f; + size_t n; + ripemd160_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR ); + + ripemd160_init( &ctx ); + ripemd160_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + ripemd160_update( &ctx, buf, n ); + + ripemd160_finish( &ctx, output ); + ripemd160_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * RIPEMD-160 HMAC context setup + */ +void ripemd160_hmac_starts( ripemd160_context *ctx, + const unsigned char *key, size_t keylen ) +{ + size_t i; + unsigned char sum[20]; + + if( keylen > 64 ) + { + ripemd160( key, keylen, sum ); + keylen = 20; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + ripemd160_starts( ctx ); + ripemd160_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * RIPEMD-160 HMAC process buffer + */ +void ripemd160_hmac_update( ripemd160_context *ctx, + const unsigned char *input, size_t ilen ) +{ + ripemd160_update( ctx, input, ilen ); +} + +/* + * RIPEMD-160 HMAC final digest + */ +void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] ) +{ + unsigned char tmpbuf[20]; + + ripemd160_finish( ctx, tmpbuf ); + ripemd160_starts( ctx ); + ripemd160_update( ctx, ctx->opad, 64 ); + ripemd160_update( ctx, tmpbuf, 20 ); + ripemd160_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * RIPEMD-160 HMAC context reset + */ +void ripemd160_hmac_reset( ripemd160_context *ctx ) +{ + ripemd160_starts( ctx ); + ripemd160_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-RIPEMD-160( hmac key, input buffer ) + */ +void ripemd160_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + ripemd160_context ctx; + + ripemd160_init( &ctx ); + ripemd160_hmac_starts( &ctx, key, keylen ); + ripemd160_hmac_update( &ctx, input, ilen ); + ripemd160_hmac_finish( &ctx, output ); + ripemd160_free( &ctx ); +} + + +#if defined(POLARSSL_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/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 }, +}; + +static const unsigned char ripemd160_test_hmac[KEYS][TESTS][20] = +{ + { + { 0xcf, 0x38, 0x76, 0x77, 0xbf, 0xda, 0x84, 0x83, 0xe6, 0x3b, + 0x57, 0xe0, 0x6c, 0x3b, 0x5e, 0xcd, 0x8b, 0x7f, 0xc0, 0x55 }, + { 0x0d, 0x35, 0x1d, 0x71, 0xb7, 0x8e, 0x36, 0xdb, 0xb7, 0x39, + 0x1c, 0x81, 0x0a, 0x0d, 0x2b, 0x62, 0x40, 0xdd, 0xba, 0xfc }, + { 0xf7, 0xef, 0x28, 0x8c, 0xb1, 0xbb, 0xcc, 0x61, 0x60, 0xd7, + 0x65, 0x07, 0xe0, 0xa3, 0xbb, 0xf7, 0x12, 0xfb, 0x67, 0xd6 }, + { 0xf8, 0x36, 0x62, 0xcc, 0x8d, 0x33, 0x9c, 0x22, 0x7e, 0x60, + 0x0f, 0xcd, 0x63, 0x6c, 0x57, 0xd2, 0x57, 0x1b, 0x1c, 0x34 }, + { 0x84, 0x3d, 0x1c, 0x4e, 0xb8, 0x80, 0xac, 0x8a, 0xc0, 0xc9, + 0xc9, 0x56, 0x96, 0x50, 0x79, 0x57, 0xd0, 0x15, 0x5d, 0xdb }, + { 0x60, 0xf5, 0xef, 0x19, 0x8a, 0x2d, 0xd5, 0x74, 0x55, 0x45, + 0xc1, 0xf0, 0xc4, 0x7a, 0xa3, 0xfb, 0x57, 0x76, 0xf8, 0x81 }, + { 0xe4, 0x9c, 0x13, 0x6a, 0x9e, 0x56, 0x27, 0xe0, 0x68, 0x1b, + 0x80, 0x8a, 0x3b, 0x97, 0xe6, 0xa6, 0xe6, 0x61, 0xae, 0x79 }, + { 0x31, 0xbe, 0x3c, 0xc9, 0x8c, 0xee, 0x37, 0xb7, 0x9b, 0x06, + 0x19, 0xe3, 0xe1, 0xc2, 0xbe, 0x4f, 0x1a, 0xa5, 0x6e, 0x6c }, + }, + { + { 0xfe, 0x69, 0xa6, 0x6c, 0x74, 0x23, 0xee, 0xa9, 0xc8, 0xfa, + 0x2e, 0xff, 0x8d, 0x9d, 0xaf, 0xb4, 0xf1, 0x7a, 0x62, 0xf5 }, + { 0x85, 0x74, 0x3e, 0x89, 0x9b, 0xc8, 0x2d, 0xbf, 0xa3, 0x6f, + 0xaa, 0xa7, 0xa2, 0x5b, 0x7c, 0xfd, 0x37, 0x24, 0x32, 0xcd }, + { 0x6e, 0x4a, 0xfd, 0x50, 0x1f, 0xa6, 0xb4, 0xa1, 0x82, 0x3c, + 0xa3, 0xb1, 0x0b, 0xd9, 0xaa, 0x0b, 0xa9, 0x7b, 0xa1, 0x82 }, + { 0x2e, 0x06, 0x6e, 0x62, 0x4b, 0xad, 0xb7, 0x6a, 0x18, 0x4c, + 0x8f, 0x90, 0xfb, 0xa0, 0x53, 0x33, 0x0e, 0x65, 0x0e, 0x92 }, + { 0x07, 0xe9, 0x42, 0xaa, 0x4e, 0x3c, 0xd7, 0xc0, 0x4d, 0xed, + 0xc1, 0xd4, 0x6e, 0x2e, 0x8c, 0xc4, 0xc7, 0x41, 0xb3, 0xd9 }, + { 0xb6, 0x58, 0x23, 0x18, 0xdd, 0xcf, 0xb6, 0x7a, 0x53, 0xa6, + 0x7d, 0x67, 0x6b, 0x8a, 0xd8, 0x69, 0xad, 0xed, 0x62, 0x9a }, + { 0xf1, 0xbe, 0x3e, 0xe8, 0x77, 0x70, 0x31, 0x40, 0xd3, 0x4f, + 0x97, 0xea, 0x1a, 0xb3, 0xa0, 0x7c, 0x14, 0x13, 0x33, 0xe2 }, + { 0x85, 0xf1, 0x64, 0x70, 0x3e, 0x61, 0xa6, 0x31, 0x31, 0xbe, + 0x7e, 0x45, 0x95, 0x8e, 0x07, 0x94, 0x12, 0x39, 0x04, 0xf9 }, + }, +}; + +static const unsigned char ripemd160_test_key[KEYS][20] = +{ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x23, 0x45, 0x67 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, + 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33 }, +}; + +/* + * Checkup routine + */ +int ripemd160_self_test( int verbose ) +{ + int i, j; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + 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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + for( j = 0; j < KEYS; j++ ) + { + if( verbose != 0 ) + polarssl_printf( " HMAC-RIPEMD-160 test #%d, key #%d: ", + i + 1, j + 1 ); + + ripemd160_hmac( ripemd160_test_key[j], 20, + (const unsigned char *) ripemd160_test_input[i], + strlen( ripemd160_test_input[i] ), + output ); + + if( memcmp( output, ripemd160_test_hmac[j][i], 20 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + } + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_RIPEMD160_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/rsa.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/rsa.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1681 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_RSA_C) + +#include "polarssl/rsa.h" +#include "polarssl/oid.h" + +#include <string.h> + +#if defined(POLARSSL_PKCS1_V21) +#include "polarssl/md.h" +#endif + +#if defined(POLARSSL_PKCS1_V15) && !defined(__OpenBSD__) +#include <stdlib.h> +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif + +/* + * Initialize an RSA context + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( rsa_context ) ); + + rsa_set_padding( ctx, padding, hash_id ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void rsa_set_padding( rsa_context *ctx, int padding, int hash_id ) +{ + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +#if defined(POLARSSL_GENPRIME) + +/* + * Generate an RSA keypair + */ +int rsa_gen_key( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret; + mpi P1, Q1, H, G; + + if( f_rng == NULL || nbits < 128 || exponent < 3 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G ); + + /* + * find primes P and Q with Q < P so that: + * GCD( E, (P-1)*(Q-1) ) == 1 + */ + MPI_CHK( mpi_lset( &ctx->E, exponent ) ); + + do + { + MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, + f_rng, p_rng ) ); + + MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, + f_rng, p_rng ) ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) + mpi_swap( &ctx->P, &ctx->Q ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + continue; + + MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + if( mpi_msb( &ctx->N ) != nbits ) + continue; + + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + } + while( 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 + */ + MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); + MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); + + ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; + +cleanup: + + mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G ); + + if( ret != 0 ) + { + rsa_free( ctx ); + return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif /* POLARSSL_GENPRIME */ + +/* + * Check a public RSA key + */ +int rsa_check_pubkey( const rsa_context *ctx ) +{ + if( !ctx->N.p || !ctx->E.p ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( ( ctx->N.p[0] & 1 ) == 0 || + ( ctx->E.p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->N ) < 128 || + mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->E ) < 2 || + mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + return( 0 ); +} + +/* + * Check a private RSA key + */ +int rsa_check_privkey( const rsa_context *ctx ) +{ + int ret; + mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; + + if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) + return( ret ); + + if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 ); + mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 ); + mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ ); + mpi_init( &QP ); + + MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); + MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + + MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); + MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); + MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); + + MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); + MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); + MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); + /* + * Check for a valid PKCS1v2 private key + */ + if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || + mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || + mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || + mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || + mpi_cmp_int( &L2, 0 ) != 0 || + mpi_cmp_int( &I, 1 ) != 0 || + mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED; + } + +cleanup: + mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 ); + mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 ); + mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ ); + mpi_free( &QP ); + + if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED ) + return( ret ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret ); + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int rsa_check_pub_priv( const rsa_context *pub, const rsa_context *prv ) +{ + if( rsa_check_pubkey( pub ) != 0 || + rsa_check_privkey( prv ) != 0 ) + { + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mpi T; + + mpi_init( &T ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_lock( &ctx->mutex ); +#endif + + olen = ctx->len; + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_unlock( &ctx->mutex ); +#endif + + mpi_free( &T ); + + if( ret != 0 ) + return( POLARSSL_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( rsa_context *ctx, mpi *Vi, mpi *Vf, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_lock( &ctx->mutex ); +#endif + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto done; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + return( POLARSSL_ERR_RSA_RNG_FAILED ); + + MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + MPI_CHK( mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + } while( mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); + + /* Blinding value: Vi = Vf^(-e) mod N */ + MPI_CHK( mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + MPI_CHK( mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + +done: + if( Vi != &ctx->Vi ) + { + MPI_CHK( mpi_copy( Vi, &ctx->Vi ) ); + MPI_CHK( mpi_copy( Vf, &ctx->Vf ) ); + } + +cleanup: +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_unlock( &ctx->mutex ); +#endif + + return( ret ); +} + +/* + * Do an RSA private key operation + */ +int rsa_private( 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; + mpi T, T1, T2; + mpi *Vi, *Vf; + + /* + * When using the Chinese Remainder Theorem, we use blinding values. + * Without threading, we just read them directly from the context, + * otherwise we make a local copy in order to reduce locking contention. + */ +#if defined(POLARSSL_THREADING_C) + mpi Vi_copy, Vf_copy; + + mpi_init( &Vi_copy ); mpi_init( &Vf_copy ); + Vi = &Vi_copy; + Vf = &Vf_copy; +#else + Vi = &ctx->Vi; + Vf = &ctx->Vf; +#endif + + mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MPI_CHK( rsa_prepare_blinding( ctx, Vi, Vf, f_rng, p_rng ) ); + MPI_CHK( mpi_mul_mpi( &T, &T, Vi ) ); + MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_lock( &ctx->mutex ); +#endif + +#if defined(POLARSSL_RSA_NO_CRT) + MPI_CHK( 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 + */ + MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); + MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (T1 - T2) * (Q^-1 mod P) mod P + */ + MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); + MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); + + /* + * T = T2 + T * Q + */ + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); + MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); +#endif /* POLARSSL_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MPI_CHK( mpi_mul_mpi( &T, &T, Vf ) ); + MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + olen = ctx->len; + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_unlock( &ctx->mutex ); + mpi_free( &Vi_copy ); mpi_free( &Vf_copy ); +#endif + mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(POLARSSL_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, md_context_t *md_ctx ) +{ + unsigned char mask[POLARSSL_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + + memset( mask, 0, POLARSSL_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = md_ctx->md_info->size; + + // Generate and apply dbMask + // + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + md_starts( md_ctx ); + md_update( md_ctx, src, slen ); + md_update( md_ctx, counter, 4 ); + md_finish( md_ctx, mask ); + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int rsa_rsaes_oaep_encrypt( 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 md_info_t *md_info; + md_context_t md_ctx; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_info = md_info_from_type( (md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = md_get_size( md_info ); + + if( olen < ilen + 2 * hlen + 2 ) + return( POLARSSL_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( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + // Construct DB + // + md( md_info, label, label_len, p ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + memcpy( p, input, ilen ); + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + // 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 ); + + md_free( &md_ctx ); + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, output, output ) + : rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int rsa_rsaes_pkcs1_v15_encrypt( 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 == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( olen < ilen + 11 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == RSA_PUBLIC ) + { + *p++ = 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( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, output, output ) + : rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int rsa_pkcs1_encrypt( 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(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int rsa_rsaes_oaep_decrypt( 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[POLARSSL_MPI_MAX_SIZE]; + unsigned char lhash[POLARSSL_MD_MAX_SIZE]; + unsigned int hlen; + const md_info_t *md_info; + md_context_t md_ctx; + + /* + * Parameters sanity checks + */ + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_info = md_info_from_type( (md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, input, buf ) + : rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + return( ret ); + + /* + * Unmask data and generate lHash + */ + hlen = md_get_size( md_info ); + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + /* Generate lHash */ + 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 ); + + 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( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if( ilen - ( p - buf ) > output_max_len ) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int rsa_rsaes_pkcs1_v15_decrypt( 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[POLARSSL_MPI_MAX_SIZE]; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, input, buf ) + : 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 == RSA_PRIVATE ) + { + bad |= *p++ ^ 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++ ^ 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( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if( ilen - ( p - buf ) > output_max_len ) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int rsa_pkcs1_decrypt( 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(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int rsa_rsassa_pss_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + 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[POLARSSL_MD_MAX_SIZE]; + unsigned int slen, hlen, offset = 0; + int ret; + size_t msb; + const md_info_t *md_info; + md_context_t md_ctx; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != POLARSSL_MD_NONE ) + { + // Gather length of hash to sign + // + md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = md_get_size( md_info ); + } + + md_info = md_info_from_type( (md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hlen = md_get_size( md_info ); + slen = hlen; + + if( olen < hlen + slen + 2 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + memset( sig, 0, olen ); + + // Generate salt of length slen + // + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + // Note: EMSA-PSS encoding is over the length of N - 1 bits + // + msb = mpi_msb( &ctx->N ) - 1; + p += olen - hlen * 2 - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + // Generate H = Hash( M' ) + // + md_starts( &md_ctx ); + md_update( &md_ctx, p, 8 ); + md_update( &md_ctx, hash, hashlen ); + md_update( &md_ctx, salt, slen ); + 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 ); + + md_free( &md_ctx ); + + msb = mpi_msb( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, sig ) + : rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_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 rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + 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; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + nb_pad = olen - 3; + + if( md_alg != POLARSSL_MD_NONE ) + { + const md_info_t *md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= 10 + oid_size; + + hashlen = md_get_size( md_info ); + } + + nb_pad -= hashlen; + + if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + if( md_alg == POLARSSL_MD_NONE ) + { + memcpy( p, hash, hashlen ); + } + else + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = ASN1_NULL; + *p++ = 0x00; + *p++ = ASN1_OCTET_STRING; + *p++ = hashlen; + memcpy( p, hash, hashlen ); + } + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, sig ) + : rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int rsa_rsassa_pss_verify_ext( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + 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[POLARSSL_MPI_MAX_SIZE]; + unsigned char result[POLARSSL_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t slen, msb; + const md_info_t *md_info; + md_context_t md_ctx; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if( md_alg != POLARSSL_MD_NONE ) + { + // Gather length of hash to sign + // + md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = md_get_size( md_info ); + } + + md_info = md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hlen = 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 = mpi_msb( &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( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + 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 ) + { + md_free( &md_ctx ); + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + /* Actual salt len */ + slen -= p - buf; + + if( expected_salt_len != RSA_SALT_LEN_ANY && + slen != (size_t) expected_salt_len ) + { + md_free( &md_ctx ); + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + // Generate H = Hash( M' ) + // + md_starts( &md_ctx ); + md_update( &md_ctx, zeros, 8 ); + md_update( &md_ctx, hash, hashlen ); + md_update( &md_ctx, p, slen ); + md_finish( &md_ctx, result ); + + md_free( &md_ctx ); + + if( memcmp( p + slen, result, hlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int rsa_rsassa_pss_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + md_type_t mgf1_hash_id = ( ctx->hash_id != POLARSSL_MD_NONE ) + ? (md_type_t) ctx->hash_id + : md_alg; + + return( rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + 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[POLARSSL_MPI_MAX_SIZE]; + md_type_t msg_md_alg; + const md_info_t *md_info; + asn1_buf oid; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( *p++ != 0 || *p++ != RSA_SIGN ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + while( *p != 0 ) + { + if( p >= buf + siglen - 1 || *p != 0xFF ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + p++; + } + p++; + + len = siglen - ( p - buf ); + + if( len == hashlen && md_alg == POLARSSL_MD_NONE ) + { + if( memcmp( p, hash, hashlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + hashlen = md_get_size( md_info ); + + end = p + len; + + // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure + // + if( ( ret = asn1_get_tag( &p, end, &asn1_len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len + 2 != len ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = asn1_get_tag( &p, end, &asn1_len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len + 6 + hashlen != len ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = asn1_get_tag( &p, end, &oid.len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + oid.p = p; + p += oid.len; + + if( oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( md_alg != msg_md_alg ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + /* + * assume the algorithm parameters must be NULL + */ + if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_NULL ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len != hashlen ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( memcmp( p, hash, hashlen ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + p += hashlen; + + if( p != end ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int rsa_copy( rsa_context *dst, const rsa_context *src ) +{ + int ret; + + dst->ver = src->ver; + dst->len = src->len; + + MPI_CHK( mpi_copy( &dst->N, &src->N ) ); + MPI_CHK( mpi_copy( &dst->E, &src->E ) ); + + MPI_CHK( mpi_copy( &dst->D, &src->D ) ); + MPI_CHK( mpi_copy( &dst->P, &src->P ) ); + MPI_CHK( mpi_copy( &dst->Q, &src->Q ) ); + MPI_CHK( mpi_copy( &dst->DP, &src->DP ) ); + MPI_CHK( mpi_copy( &dst->DQ, &src->DQ ) ); + MPI_CHK( mpi_copy( &dst->QP, &src->QP ) ); + + MPI_CHK( mpi_copy( &dst->RN, &src->RN ) ); + MPI_CHK( mpi_copy( &dst->RP, &src->RP ) ); + MPI_CHK( mpi_copy( &dst->RQ, &src->RQ ) ); + + MPI_CHK( mpi_copy( &dst->Vi, &src->Vi ) ); + MPI_CHK( mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void rsa_free( rsa_context *ctx ) +{ + mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf ); + mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN ); + mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP ); + mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D ); + mpi_free( &ctx->E ); mpi_free( &ctx->N ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &ctx->mutex ); +#endif +} + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define 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(POLARSSL_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 /* POLARSSL_PKCS1_V15 */ + +/* + * Checkup routine + */ +int rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(POLARSSL_PKCS1_V15) + size_t len; + rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(POLARSSL_SHA1_C) + unsigned char sha1sum[20]; +#endif + + rsa_init( &rsa, RSA_PKCS_V15, 0 ); + + rsa.len = KEY_LEN; + MPI_CHK( mpi_read_string( &rsa.N , 16, RSA_N ) ); + MPI_CHK( mpi_read_string( &rsa.E , 16, RSA_E ) ); + MPI_CHK( mpi_read_string( &rsa.D , 16, RSA_D ) ); + MPI_CHK( mpi_read_string( &rsa.P , 16, RSA_P ) ); + MPI_CHK( mpi_read_string( &rsa.Q , 16, RSA_Q ) ); + MPI_CHK( mpi_read_string( &rsa.DP, 16, RSA_DP ) ); + MPI_CHK( mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); + MPI_CHK( mpi_read_string( &rsa.QP, 16, RSA_QP ) ); + + if( verbose != 0 ) + polarssl_printf( " RSA key validation: " ); + + if( rsa_check_pubkey( &rsa ) != 0 || + rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( rsa_pkcs1_encrypt( &rsa, myrand, NULL, RSA_PUBLIC, PT_LEN, + rsa_plaintext, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 decryption : " ); + + if( rsa_pkcs1_decrypt( &rsa, myrand, NULL, RSA_PRIVATE, &len, + rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + +#if defined(POLARSSL_SHA1_C) + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 data sign : " ); + + sha1( rsa_plaintext, PT_LEN, sha1sum ); + + if( rsa_pkcs1_sign( &rsa, myrand, NULL, RSA_PRIVATE, POLARSSL_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 sig. verify: " ); + + if( rsa_pkcs1_verify( &rsa, NULL, NULL, RSA_PUBLIC, POLARSSL_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n" ); +#endif /* POLARSSL_SHA1_C */ + +cleanup: + rsa_free( &rsa ); +#else /* POLARSSL_PKCS1_V15 */ + ((void) verbose); +#endif /* POLARSSL_PKCS1_V15 */ + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_RSA_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/sha1.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/sha1.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,664 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SHA1_C) + +#include "polarssl/sha1.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_SHA1_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void sha1_init( sha1_context *ctx ) +{ + memset( ctx, 0, sizeof( sha1_context ) ); +} + +void sha1_free( sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( sha1_context ) ); +} + +/* + * SHA-1 context setup + */ +void sha1_starts( 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; +} + +void sha1_process( 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; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( 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 ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + 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 sha1_finish( 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 ); + + sha1_update( ctx, sha1_padding, padn ); + 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 /* !POLARSSL_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_init( &ctx ); + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); + sha1_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-1( file contents ) + */ +int sha1_file( const char *path, unsigned char output[20] ) +{ + FILE *f; + size_t n; + sha1_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); + + sha1_init( &ctx ); + sha1_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha1_update( &ctx, buf, n ); + + sha1_finish( &ctx, output ); + sha1_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-1 HMAC context setup + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[20]; + + if( keylen > 64 ) + { + sha1( key, keylen, sum ); + keylen = 20; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * SHA-1 HMAC process buffer + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, + size_t ilen ) +{ + sha1_update( ctx, input, ilen ); +} + +/* + * SHA-1 HMAC final digest + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned char tmpbuf[20]; + + sha1_finish( ctx, tmpbuf ); + sha1_starts( ctx ); + sha1_update( ctx, ctx->opad, 64 ); + sha1_update( ctx, tmpbuf, 20 ); + sha1_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * SHA1 HMAC context reset + */ +void sha1_hmac_reset( sha1_context *ctx ) +{ + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-1( hmac key, input buffer ) + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_init( &ctx ); + sha1_hmac_starts( &ctx, key, keylen ); + sha1_hmac_update( &ctx, input, ilen ); + sha1_hmac_finish( &ctx, output ); + sha1_free( &ctx ); +} + +#if defined(POLARSSL_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 } +}; + +/* + * RFC 2202 test vectors + */ +static const unsigned char sha1_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 80 times */ + { "" } +}; + +static const int sha1_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 80, 80 +}; + +static const unsigned char sha1_hmac_test_buf[7][74] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "Test Using Larger Than Block-Size Key and Larger" + " Than One Block-Size Data" } +}; + +static const int sha1_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 73 +}; + +static const unsigned char sha1_hmac_test_sum[7][20] = +{ + { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, + 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 }, + { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, + 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 }, + { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, + 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 }, + { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, + 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA }, + { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, + 0x7B, 0xE1 }, + { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, + 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 }, + { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, + 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 } +}; + +/* + * Checkup routine + */ +int sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + sha1_context ctx; + + sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " SHA-1 test #%d: ", i + 1 ); + + sha1_starts( &ctx ); + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha1_update( &ctx, buf, buflen ); + } + else + sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + + sha1_finish( &ctx, sha1sum ); + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " HMAC-SHA-1 test #%d: ", i + 1 ); + + if( i == 5 || i == 6 ) + { + memset( buf, 0xAA, buflen = 80 ); + sha1_hmac_starts( &ctx, buf, buflen ); + } + else + sha1_hmac_starts( &ctx, sha1_hmac_test_key[i], + sha1_hmac_test_keylen[i] ); + + sha1_hmac_update( &ctx, sha1_hmac_test_buf[i], + sha1_hmac_test_buflen[i] ); + + sha1_hmac_finish( &ctx, sha1sum ); + + buflen = ( i == 4 ) ? 12 : 20; + + if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + sha1_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_SHA1_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/sha256.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/sha256.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,745 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SHA256_C) + +#include "polarssl/sha256.h" + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_SHA256_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void sha256_init( sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( sha256_context ) ); +} + +void sha256_free( sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( sha256_context ) ); +} + +/* + * SHA-256 context setup + */ +void sha256_starts( 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; +} + +void sha256_process( sha256_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A, B, C, D, E, F, G, H; + + 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 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; \ +} + + 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]; + + P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); + P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); + P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); + P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); + P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); + P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); + P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); + P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); + P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); + P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); + P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); + P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); + P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); + P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); + P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); + P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); + P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); + P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); + P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); + P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); + P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); + P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); + P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); + P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); + P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); + P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); + P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); + P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); + P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); + P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); + P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); + P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); + P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); + P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); + P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); + P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); + P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); + P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); + P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); + P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); + P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); + P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); + P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); + P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); + P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); + P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); + P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); + P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); + P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); + P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); + P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); + P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); + P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); + P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); + P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); + P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); + P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); + P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); + P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); + P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); + P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); + P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); + P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); + P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); + + 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; +} + +/* + * SHA-256 process buffer + */ +void sha256_update( 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 ); + sha256_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + 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 sha256_finish( 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 ); + + sha256_update( ctx, sha256_padding, padn ); + 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 /* !POLARSSL_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +void sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha256_context ctx; + + sha256_init( &ctx ); + sha256_starts( &ctx, is224 ); + sha256_update( &ctx, input, ilen ); + sha256_finish( &ctx, output ); + sha256_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-256( file contents ) + */ +int sha256_file( const char *path, unsigned char output[32], int is224 ) +{ + FILE *f; + size_t n; + sha256_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA256_FILE_IO_ERROR ); + + sha256_init( &ctx ); + sha256_starts( &ctx, is224 ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha256_update( &ctx, buf, n ); + + sha256_finish( &ctx, output ); + sha256_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA256_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-256 HMAC context setup + */ +void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key, + size_t keylen, int is224 ) +{ + size_t i; + unsigned char sum[32]; + + if( keylen > 64 ) + { + sha256( key, keylen, sum, is224 ); + keylen = ( is224 ) ? 28 : 32; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha256_starts( ctx, is224 ); + sha256_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * SHA-256 HMAC process buffer + */ +void sha256_hmac_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_update( ctx, input, ilen ); +} + +/* + * SHA-256 HMAC final digest + */ +void sha256_hmac_finish( sha256_context *ctx, unsigned char output[32] ) +{ + int is224, hlen; + unsigned char tmpbuf[32]; + + is224 = ctx->is224; + hlen = ( is224 == 0 ) ? 32 : 28; + + sha256_finish( ctx, tmpbuf ); + sha256_starts( ctx, is224 ); + sha256_update( ctx, ctx->opad, 64 ); + sha256_update( ctx, tmpbuf, hlen ); + sha256_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * SHA-256 HMAC context reset + */ +void sha256_hmac_reset( sha256_context *ctx ) +{ + sha256_starts( ctx, ctx->is224 ); + sha256_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-256( hmac key, input buffer ) + */ +void sha256_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha256_context ctx; + + sha256_init( &ctx ); + sha256_hmac_starts( &ctx, key, keylen, is224 ); + sha256_hmac_update( &ctx, input, ilen ); + sha256_hmac_finish( &ctx, output ); + sha256_free( &ctx ); +} + +#if defined(POLARSSL_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 } +}; + +/* + * RFC 4231 test vectors + */ +static const unsigned char sha256_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 131 times */ + { "" } +}; + +static const int sha256_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 131, 131 +}; + +static const unsigned char sha256_hmac_test_buf[7][153] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "This is a test using a larger than block-size key " + "and a larger than block-size data. The key needs to " + "be hashed before being used by the HMAC algorithm." } +}; + +static const int sha256_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 152 +}; + +static const unsigned char sha256_hmac_test_sum[14][32] = +{ + /* + * HMAC-SHA-224 test vectors + */ + { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19, + 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F, + 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F, + 0x53, 0x68, 0x4B, 0x22 }, + { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF, + 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F, + 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00, + 0x8F, 0xD0, 0x5E, 0x44 }, + { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6, + 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64, + 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1, + 0xEC, 0x83, 0x33, 0xEA }, + { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC, + 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C, + 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D, + 0xE7, 0xAF, 0xEC, 0x5A }, + { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37, + 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 }, + { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD, + 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2, + 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27, + 0x3F, 0xA6, 0x87, 0x0E }, + { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02, + 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD, + 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9, + 0xF6, 0xF5, 0x65, 0xD1 }, + + /* + * HMAC-SHA-256 test vectors + */ + { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53, + 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B, + 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7, + 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 }, + { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E, + 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7, + 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83, + 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 }, + { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46, + 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7, + 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22, + 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE }, + { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E, + 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A, + 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07, + 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B }, + { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0, + 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B }, + { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F, + 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F, + 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14, + 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 }, + { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB, + 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44, + 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93, + 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 } +}; + +/* + * Checkup routine + */ +int sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha256sum[32]; + sha256_context ctx; + + sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + polarssl_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + sha256_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha256_update( &ctx, buf, buflen ); + } + else + sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + + sha256_finish( &ctx, sha256sum ); + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 14; i++ ) + { + j = i % 7; + k = i < 7; + + if( verbose != 0 ) + polarssl_printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( j == 5 || j == 6 ) + { + memset( buf, 0xAA, buflen = 131 ); + sha256_hmac_starts( &ctx, buf, buflen, k ); + } + else + sha256_hmac_starts( &ctx, sha256_hmac_test_key[j], + sha256_hmac_test_keylen[j], k ); + + sha256_hmac_update( &ctx, sha256_hmac_test_buf[j], + sha256_hmac_test_buflen[j] ); + + sha256_hmac_finish( &ctx, sha256sum ); + + buflen = ( j == 4 ) ? 16 : 32 - k * 4; + + if( memcmp( sha256sum, sha256_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + sha256_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_SHA256_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/sha512.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/sha512.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,805 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SHA512_C) + +#include "polarssl/sha512.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include <string.h> + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#endif + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_SHA512_ALT) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +void sha512_init( sha512_context *ctx ) +{ + memset( ctx, 0, sizeof( sha512_context ) ); +} + +void sha512_free( sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( sha512_context ) ); +} + +/* + * SHA-512 context setup + */ +void sha512_starts( 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; +} + +void sha512_process( 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; +} + +/* + * SHA-512 process buffer + */ +void sha512_update( 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 ); + sha512_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + 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 sha512_finish( 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 ); + + sha512_update( ctx, sha512_padding, padn ); + 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 /* !POLARSSL_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +void sha512( const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ) +{ + sha512_context ctx; + + sha512_init( &ctx ); + sha512_starts( &ctx, is384 ); + sha512_update( &ctx, input, ilen ); + sha512_finish( &ctx, output ); + sha512_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-512( file contents ) + */ +int sha512_file( const char *path, unsigned char output[64], int is384 ) +{ + FILE *f; + size_t n; + sha512_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA512_FILE_IO_ERROR ); + + sha512_init( &ctx ); + sha512_starts( &ctx, is384 ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha512_update( &ctx, buf, n ); + + sha512_finish( &ctx, output ); + sha512_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA512_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-512 HMAC context setup + */ +void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key, + size_t keylen, int is384 ) +{ + size_t i; + unsigned char sum[64]; + + if( keylen > 128 ) + { + sha512( key, keylen, sum, is384 ); + keylen = ( is384 ) ? 48 : 64; + key = sum; + } + + memset( ctx->ipad, 0x36, 128 ); + memset( ctx->opad, 0x5C, 128 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha512_starts( ctx, is384 ); + sha512_update( ctx, ctx->ipad, 128 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * SHA-512 HMAC process buffer + */ +void sha512_hmac_update( sha512_context *ctx, + const unsigned char *input, size_t ilen ) +{ + sha512_update( ctx, input, ilen ); +} + +/* + * SHA-512 HMAC final digest + */ +void sha512_hmac_finish( sha512_context *ctx, unsigned char output[64] ) +{ + int is384, hlen; + unsigned char tmpbuf[64]; + + is384 = ctx->is384; + hlen = ( is384 == 0 ) ? 64 : 48; + + sha512_finish( ctx, tmpbuf ); + sha512_starts( ctx, is384 ); + sha512_update( ctx, ctx->opad, 128 ); + sha512_update( ctx, tmpbuf, hlen ); + sha512_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * SHA-512 HMAC context reset + */ +void sha512_hmac_reset( sha512_context *ctx ) +{ + sha512_starts( ctx, ctx->is384 ); + sha512_update( ctx, ctx->ipad, 128 ); +} + +/* + * output = HMAC-SHA-512( hmac key, input buffer ) + */ +void sha512_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ) +{ + sha512_context ctx; + + sha512_init( &ctx ); + sha512_hmac_starts( &ctx, key, keylen, is384 ); + sha512_hmac_update( &ctx, input, ilen ); + sha512_hmac_finish( &ctx, output ); + sha512_free( &ctx ); +} + +#if defined(POLARSSL_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 } +}; + +/* + * RFC 4231 test vectors + */ +static const unsigned char sha512_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 131 times */ + { "" } +}; + +static const int sha512_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 131, 131 +}; + +static const unsigned char sha512_hmac_test_buf[7][153] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "This is a test using a larger than block-size key " + "and a larger than block-size data. The key needs to " + "be hashed before being used by the HMAC algorithm." } +}; + +static const int sha512_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 152 +}; + +static const unsigned char sha512_hmac_test_sum[14][64] = +{ + /* + * HMAC-SHA-384 test vectors + */ + { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62, + 0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F, + 0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6, + 0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C, + 0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F, + 0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 }, + { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31, + 0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B, + 0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47, + 0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E, + 0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7, + 0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 }, + { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A, + 0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F, + 0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB, + 0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B, + 0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9, + 0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 }, + { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85, + 0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7, + 0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C, + 0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E, + 0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79, + 0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB }, + { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23, + 0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 }, + { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90, + 0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4, + 0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F, + 0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6, + 0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82, + 0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 }, + { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D, + 0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C, + 0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A, + 0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5, + 0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D, + 0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E }, + + /* + * HMAC-SHA-512 test vectors + */ + { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D, + 0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0, + 0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78, + 0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE, + 0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02, + 0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4, + 0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70, + 0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 }, + { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2, + 0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3, + 0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6, + 0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54, + 0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A, + 0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD, + 0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B, + 0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 }, + { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84, + 0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9, + 0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36, + 0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39, + 0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8, + 0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07, + 0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26, + 0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB }, + { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69, + 0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7, + 0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D, + 0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB, + 0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4, + 0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63, + 0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D, + 0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD }, + { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53, + 0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 }, + { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB, + 0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4, + 0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1, + 0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52, + 0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98, + 0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52, + 0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC, + 0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 }, + { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA, + 0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD, + 0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86, + 0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44, + 0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1, + 0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15, + 0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60, + 0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 } +}; + +/* + * Checkup routine + */ +int sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha512sum[64]; + sha512_context ctx; + + sha512_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + polarssl_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + sha512_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha512_update( &ctx, buf, buflen ); + } + else + sha512_update( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + + sha512_finish( &ctx, sha512sum ); + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 14; i++ ) + { + j = i % 7; + k = i < 7; + + if( verbose != 0 ) + polarssl_printf( " HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( j == 5 || j == 6 ) + { + memset( buf, 0xAA, buflen = 131 ); + sha512_hmac_starts( &ctx, buf, buflen, k ); + } + else + sha512_hmac_starts( &ctx, sha512_hmac_test_key[j], + sha512_hmac_test_keylen[j], k ); + + sha512_hmac_update( &ctx, sha512_hmac_test_buf[j], + sha512_hmac_test_buflen[j] ); + + sha512_hmac_finish( &ctx, sha512sum ); + + buflen = ( j == 4 ) ? 16 : 64 - k * 16; + + if( memcmp( sha512sum, sha512_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + sha512_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_SHA512_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ssl_cache.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ssl_cache.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,330 @@ +/* + * SSL session cache implementation + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_CACHE_C) + +#include "polarssl/ssl_cache.h" + +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +void ssl_cache_init( ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( ssl_cache_context ) ); + + cache->timeout = SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &cache->mutex ); +#endif +} + +int ssl_cache_get( void *data, ssl_session *session ) +{ + int ret = 1; +#if defined(POLARSSL_HAVE_TIME) + time_t t = time( NULL ); +#endif + ssl_cache_context *cache = (ssl_cache_context *) data; + ssl_cache_entry *cur, *entry; + +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(POLARSSL_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->length != entry->session.length ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.length ) != 0 ) + continue; + + memcpy( session->master, entry->session.master, 48 ); + + session->verify_result = entry->session.verify_result; + +#if defined(POLARSSL_X509_CRT_PARSE_C) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + if( ( session->peer_cert = polarssl_malloc( + sizeof(x509_crt) ) ) == NULL ) + { + ret = 1; + goto exit; + } + + x509_crt_init( session->peer_cert ); + if( x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + polarssl_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + ret = 0; + goto exit; + } + +exit: +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int ssl_cache_set( void *data, const ssl_session *session ) +{ + int ret = 1; +#if defined(POLARSSL_HAVE_TIME) + time_t t = time( NULL ), oldest = 0; + ssl_cache_entry *old = NULL; +#endif + ssl_cache_context *cache = (ssl_cache_context *) data; + ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(POLARSSL_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.length ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(POLARSSL_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(POLARSSL_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* POLARSSL_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 /* POLARSSL_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = polarssl_malloc( sizeof(ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + memset( cur, 0, sizeof(ssl_cache_entry) ); + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(POLARSSL_HAVE_TIME) + cur->timestamp = t; +#endif + } + + memcpy( &cur->session, session, sizeof( ssl_session ) ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + polarssl_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(x509_buf) ); + } + + /* + * Store peer certificate + */ + if( session->peer_cert != NULL ) + { + cur->peer_cert.p = polarssl_malloc( 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 /* POLARSSL_X509_CRT_PARSE_C */ + + ret = 0; + +exit: +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(POLARSSL_HAVE_TIME) +void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* POLARSSL_HAVE_TIME */ + +void ssl_cache_set_max_entries( ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void ssl_cache_free( ssl_cache_context *cache ) +{ + ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + ssl_session_free( &prv->session ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + polarssl_free( prv->peer_cert.p ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + polarssl_free( prv ); + } + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &cache->mutex ); +#endif +} + +#endif /* POLARSSL_SSL_CACHE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ssl_ciphersuites.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ssl_ciphersuites.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1844 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_TLS_C) + +#include "polarssl/ssl_ciphersuites.h" +#include "polarssl/ssl.h" + +// #include <stdlib.h> +#include <string.h> + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* + * 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 > 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(SSL_CIPHERSUITES) + SSL_CIPHERSUITES, +#else + /* All AES-256 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + TLS_DHE_RSA_WITH_AES_256_CCM, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All AES-128 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + TLS_DHE_RSA_WITH_AES_128_CCM, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All remaining >= 128-bit ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + + /* The PSK ephemeral suites */ + TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + TLS_DHE_PSK_WITH_AES_256_CCM, + TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS_DHE_PSK_WITH_AES_256_CCM_8, + + TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + TLS_DHE_PSK_WITH_AES_128_CCM, + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS_DHE_PSK_WITH_AES_128_CCM_8, + + TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + + /* All AES-256 suites */ + TLS_RSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_256_CCM, + TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All AES-128 suites */ + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_128_CCM, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All remaining >= 128-bit suites */ + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + + /* The RSA PSK suites */ + TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + + TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + + TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The PSK suites */ + TLS_PSK_WITH_AES_256_GCM_SHA384, + TLS_PSK_WITH_AES_256_CCM, + TLS_PSK_WITH_AES_256_CBC_SHA384, + TLS_PSK_WITH_AES_256_CBC_SHA, + TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS_PSK_WITH_AES_256_CCM_8, + + TLS_PSK_WITH_AES_128_GCM_SHA256, + TLS_PSK_WITH_AES_128_CCM, + TLS_PSK_WITH_AES_128_CBC_SHA256, + TLS_PSK_WITH_AES_128_CBC_SHA, + TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS_PSK_WITH_AES_128_CCM_8, + + TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_ECDHE_PSK_WITH_RC4_128_SHA, + TLS_DHE_PSK_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_MD5, + TLS_ECDH_RSA_WITH_RC4_128_SHA, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + TLS_RSA_PSK_WITH_RC4_128_SHA, + TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + TLS_DHE_RSA_WITH_DES_CBC_SHA, + TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + TLS_ECDHE_ECDSA_WITH_NULL_SHA, + TLS_ECDHE_RSA_WITH_NULL_SHA, + TLS_ECDHE_PSK_WITH_NULL_SHA384, + TLS_ECDHE_PSK_WITH_NULL_SHA256, + TLS_ECDHE_PSK_WITH_NULL_SHA, + TLS_DHE_PSK_WITH_NULL_SHA384, + TLS_DHE_PSK_WITH_NULL_SHA256, + TLS_DHE_PSK_WITH_NULL_SHA, + + TLS_RSA_WITH_NULL_SHA256, + TLS_RSA_WITH_NULL_SHA, + TLS_RSA_WITH_NULL_MD5, + TLS_ECDH_RSA_WITH_NULL_SHA, + TLS_ECDH_ECDSA_WITH_NULL_SHA, + TLS_RSA_PSK_WITH_NULL_SHA384, + TLS_RSA_PSK_WITH_NULL_SHA256, + TLS_RSA_PSK_WITH_NULL_SHA, + TLS_PSK_WITH_NULL_SHA384, + TLS_PSK_WITH_NULL_SHA256, + TLS_PSK_WITH_NULL_SHA, + +#endif /* SSL_CIPHERSUITES */ + 0 +}; + +static const ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#if defined(POLARSSL_CCM_C) + { TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA512_C) && defined(POLARSSL_GCM_C) + { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C && POLARSSL_GCM_C */ + +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_GCM_C) + { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CCM_C) + { TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA512_C) && defined(POLARSSL_GCM_C) + { TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C && POLARSSL_GCM_C */ + +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_GCM_C) + { TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_CCM_C) + { TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_MD5_C) + { TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CCM_C) + { TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CCM_C) + { TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(POLARSSL_AES_C) + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) +#if defined(POLARSSL_MD5_C) + { TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + POLARSSL_CIPHER_NULL, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ +#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */ + + { 0, "", + POLARSSL_CIPHER_NONE, POLARSSL_MD_NONE, POLARSSL_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(SSL_CIPHERSUITES) +const int *ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +const int *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(POLARSSL_REMOVE_ARC4_CIPHERSUITES) + const ssl_ciphersuite_t *cs_info; + if( ( cs_info = ssl_ciphersuite_from_id( *p ) ) != NULL && + cs_info->cipher != POLARSSL_CIPHER_ARC4_128 ) +#else + if( ssl_ciphersuite_from_id( *p ) != NULL ) +#endif + *(q++) = *p; + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +}; +#endif /* SSL_CIPHERSUITES */ + +const ssl_ciphersuite_t *ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcasecmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite ) +{ + const ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const ssl_ciphersuite_t *cur; + + cur = ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const ssl_ciphersuite_t *cur; + + cur = ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(POLARSSL_PK_C) +pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_RSA: + case POLARSSL_KEY_EXCHANGE_DHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_RSA: + case POLARSSL_KEY_EXCHANGE_RSA_PSK: + return( POLARSSL_PK_RSA ); + + case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA: + return( POLARSSL_PK_ECDSA ); + + case POLARSSL_KEY_EXCHANGE_ECDH_RSA: + case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA: + return( POLARSSL_PK_ECKEY ); + + default: + return( POLARSSL_PK_NONE ); + } +} +#endif /* POLARSSL_PK_C */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_ECDHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_PSK: + case POLARSSL_KEY_EXCHANGE_ECDH_RSA: + case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_PSK: + case POLARSSL_KEY_EXCHANGE_RSA_PSK: + case POLARSSL_KEY_EXCHANGE_DHE_PSK: + case POLARSSL_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#endif /* POLARSSL_SSL_TLS_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ssl_cli.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ssl_cli.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,2855 @@ +/* + * SSLv3/TLSv1 client-side functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_CLI_C) + +#include "polarssl/debug.h" +#include "polarssl/ssl.h" + +#include <string.h> + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include <basetsd.h> +typedef UINT32 uint32_t; +#else +#include <inttypes.h> +#endif + +#if defined(POLARSSL_HAVE_TIME) +#include <time.h> +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +static void ssl_write_hostname_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->hostname == NULL ) + return; + + SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + /* + * 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)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME ) & 0xFF ); + + *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (ssl->hostname_len + 5) ) & 0xFF ); + + *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (ssl->hostname_len + 3) ) & 0xFF ); + + *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF ); + + memcpy( p, ssl->hostname, ssl->hostname_len ); + + *olen = ssl->hostname_len + 9; +} +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +#if defined(POLARSSL_SSL_RENEGOTIATION) +static void ssl_write_renegotiation_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->renegotiation != SSL_RENEGOTIATION ) + return; + + SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( 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 /* POLARSSL_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \ + defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED) +static void ssl_write_signature_algorithms_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + size_t sig_alg_len = 0; +#if defined(POLARSSL_RSA_C) || defined(POLARSSL_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->max_minor_ver != SSL_MINOR_VERSION_3 ) + return; + + SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ +#if defined(POLARSSL_RSA_C) +#if defined(POLARSSL_SHA512_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_SHA256_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_SHA1_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_MD5_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_MD5; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECDSA_C) +#if defined(POLARSSL_SHA512_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#if defined(POLARSSL_SHA256_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#if defined(POLARSSL_SHA1_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#if defined(POLARSSL_MD5_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_MD5; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#endif /* POLARSSL_ECDSA_C */ + + /* + * 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)( ( TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( 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 /* POLARSSL_SSL_PROTO_TLS1_2 && + POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static void ssl_write_supported_elliptic_curves_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const ecp_curve_info *info; +#if defined(POLARSSL_SSL_SET_CURVES) + const ecp_group_id *grp_id; +#else + ((void) ssl); +#endif + + *olen = 0; + + SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + +#if defined(POLARSSL_SSL_SET_CURVES) + for( grp_id = ssl->curve_list; *grp_id != POLARSSL_ECP_DP_NONE; grp_id++ ) + { + info = ecp_curve_info_from_grp_id( *grp_id ); +#else + for( info = ecp_curve_list(); info->grp_id != POLARSSL_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)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + *olen = 6 + elliptic_curve_len; +} + +static void ssl_write_supported_point_formats_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + *olen = 0; + + SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = POLARSSL_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ) { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->mfl_code; + + *olen = 5; +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->encrypt_then_mac == SSL_ETM_DISABLED || + ssl->max_minor_ver == SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " + "extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED || + ssl->max_minor_ver == SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " + "extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + size_t tlen = ssl->session_negotiate->ticket_len; + + if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( tlen ) & 0xFF ); + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || + ssl->session_negotiate->ticket_len == 0 ) + { + return; + } + + SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_ALPN) +static void ssl_write_alpn_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const char **cur; + + if( ssl->alpn_list == NULL ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_ALPN >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( 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->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 /* POLARSSL_SSL_ALPN */ + +static int ssl_write_client_hello( ssl_context *ssl ) +{ + int ret; + size_t i, n, olen, ext_len = 0; + unsigned char *buf; + unsigned char *p, *q; +#if defined(POLARSSL_HAVE_TIME) + time_t t; +#endif + const int *ciphersuites; + const ssl_ciphersuite_t *ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->f_rng == NULL ) + { + SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( POLARSSL_ERR_SSL_NO_RNG ); + } + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) +#endif + { + ssl->major_ver = ssl->min_major_ver; + ssl->minor_ver = ssl->min_minor_ver; + } + + if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 ) + { + ssl->max_major_ver = SSL_MAX_MAJOR_VERSION; + ssl->max_minor_ver = SSL_MAX_MINOR_VERSION; + } + + /* + * 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; + + *p++ = (unsigned char) ssl->max_major_ver; + *p++ = (unsigned char) ssl->max_minor_ver; + + SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(POLARSSL_HAVE_TIME) + t = time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->f_rng( ssl->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* POLARSSL_HAVE_TIME */ + + if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes, buf + 6, 32 ); + + SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 ); + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 40+n . 41+n ciphersuitelist length + * 42+n . .. ciphersuitelist + * .. . .. compression methods length + * .. . .. compression methods + * .. . .. extensions length + * .. . .. extensions + */ + n = ssl->session_negotiate->length; + + if( n < 16 || n > 32 || +#if defined(POLARSSL_SSL_RENEGOTIATION) + ssl->renegotiation != SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(POLARSSL_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(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->length = n = 32; + } + } +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); + SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; + n = 0; + q = p; + + // Skip writing ciphersuite length for now + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ciphersuite_info == NULL ) + continue; + + if( ciphersuite_info->min_minor_ver > ssl->max_minor_ver || + ciphersuite_info->max_minor_ver < ssl->min_minor_ver ) + continue; + + if( ssl->arc4_disabled == SSL_ARC4_DISABLED && + ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 ) + continue; + + SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d", + ciphersuites[i] ) ); + + n++; + *p++ = (unsigned char)( ciphersuites[i] >> 8 ); + *p++ = (unsigned char)( ciphersuites[i] ); + } + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) +#endif + { + *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); + *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO ); + n++; + } + + /* Some versions of OpenSSL don't handle it correctly if not at end */ +#if defined(POLARSSL_SSL_FALLBACK_SCSV) + if( ssl->fallback == SSL_IS_FALLBACK ) + { + SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); + *p++ = (unsigned char)( SSL_FALLBACK_SCSV >> 8 ); + *p++ = (unsigned char)( SSL_FALLBACK_SCSV ); + n++; + } +#endif + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + + SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); + + +#if defined(POLARSSL_ZLIB_SUPPORT) + SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); + SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", + SSL_COMPRESS_DEFLATE, SSL_COMPRESS_NULL ) ); + + *p++ = 2; + *p++ = SSL_COMPRESS_DEFLATE; + *p++ = SSL_COMPRESS_NULL; +#else + SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", SSL_COMPRESS_NULL ) ); + + *p++ = 1; + *p++ = SSL_COMPRESS_NULL; +#endif /* POLARSSL_ZLIB_SUPPORT */ + + // First write extensions, then the total length + // +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_RENEGOTIATION) + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \ + defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED) + ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + /* olen unused if all extensions are disabled */ + ((void) olen); + + 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 = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CLIENT_HELLO; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +static int ssl_parse_renegotiation_info( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation != 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 || + safer_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + safer_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else +#endif /* POLARSSL_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( 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->mfl_code == SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->mfl_code ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->encrypt_then_mac == SSL_ETM_DISABLED || + ssl->minor_ver == SSL_MINOR_VERSION_0 || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == SSL_MINOR_VERSION_0 || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static int ssl_parse_supported_point_formats_ext( 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 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED || + p[0] == POLARSSL_ECP_PF_COMPRESSED ) + { + ssl->handshake->ecdh_ctx.point_format = p[0]; + SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_ALPN) +static int ssl_parse_alpn_ext( 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->alpn_list == NULL ) + return( POLARSSL_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( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + + name_len = buf[2]; + if( name_len != list_len - 1 ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* POLARSSL_SSL_ALPN */ + +static int ssl_parse_server_hello( ssl_context *ssl ) +{ + int ret, i, comp; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; +#if defined(POLARSSL_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const ssl_ciphersuite_t *suite_info; +#if defined(POLARSSL_DEBUG_C) + uint32_t t; +#endif + + SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->in_msg; + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + ssl->renego_records_seen++; + + if( ssl->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->renego_max_records ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by server" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); + return( POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* POLARSSL_SSL_RENEGOTIATION */ + + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ssl->in_hslen < 42 || + buf[0] != SSL_HS_SERVER_HELLO || + buf[4] != SSL_MAJOR_VERSION_3 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( buf[5] > ssl->max_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->minor_ver = buf[5]; + + if( ssl->minor_ver < ssl->min_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "server only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", ssl->major_ver, + ssl->minor_ver, buf[4], buf[5] ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + +#if defined(POLARSSL_DEBUG_C) + t = ( (uint32_t) buf[6] << 24 ) + | ( (uint32_t) buf[7] << 16 ) + | ( (uint32_t) buf[8] << 8 ) + | ( (uint32_t) buf[9] ); + SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#endif + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + n = buf[38]; + + SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + if( n > 32 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 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 . 44+n+m extensions + */ + if( ssl->in_hslen > 43 + n ) + { + ext_len = ( ( buf[42 + n] << 8 ) + | ( buf[43 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != 44 + n + ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else if( ssl->in_hslen == 42 + n ) + { + ext_len = 0; + } + else + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + i = ( buf[39 + n] << 8 ) | buf[40 + n]; + comp = buf[41 + n]; + + /* + * Initialize update checksum functions + */ + ssl->transform_negotiate->ciphersuite_info = ssl_ciphersuite_from_id( i ); + + if( ssl->transform_negotiate->ciphersuite_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(POLARSSL_SSL_RENEGOTIATION) + ssl->renegotiation != SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->length != n || + memcmp( ssl->session_negotiate->id, buf + 39, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(POLARSSL_HAVE_TIME) + ssl->session_negotiate->start = time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->length = n; + memcpy( ssl->session_negotiate->id, buf + 39, n ); + } + else + { + ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + } + + SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) ); + SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) ); + + suite_info = ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); + if( suite_info == NULL || + ( ssl->arc4_disabled && + suite_info->cipher == POLARSSL_CIPHER_ARC4_128 ) ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + + i = 0; + while( 1 ) + { + if( ssl->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + if( comp != SSL_COMPRESS_NULL +#if defined(POLARSSL_ZLIB_SUPPORT) + && comp != SSL_COMPRESS_DEFLATE +#endif + ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 44 + n; + + 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 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case TLS_EXT_RENEGOTIATION_INFO: + SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(POLARSSL_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + case TLS_EXT_MAX_FRAGMENT_LENGTH: + SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + case TLS_EXT_TRUNCATED_HMAC: + SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + case TLS_EXT_ENCRYPT_THEN_MAC: + SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); + + if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + case TLS_EXT_EXTENDED_MASTER_SECRET: + SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); + + if( ( ret = ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + case TLS_EXT_SESSION_TICKET: + SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + case TLS_EXT_SUPPORTED_POINT_FORMATS: + 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 /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_ALPN) + case TLS_EXT_ALPN: + SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* POLARSSL_SSL_ALPN */ + + default: + 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 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(POLARSSL_SSL_RENEGOTIATION) + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* POLARSSL_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( ssl_context *ssl, unsigned char **p, + unsigned char *end ) +{ + int ret = POLARSSL_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 = dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 2, ( "dhm_read_params" ), ret ); + return( ret ); + } + + if( ssl->handshake->dhm_ctx.len < 64 || + ssl->handshake->dhm_ctx.len > 512 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (DHM length)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const ssl_context *ssl ) +{ + const ecp_curve_info *curve_info; + + curve_info = ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); + if( curve_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(POLARSSL_SSL_SET_CURVES) + if( ! ssl_curve_is_acceptable( ssl, ssl->handshake->ecdh_ctx.grp.id ) ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ecdh_read_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_server_psk_hint( ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = POLARSSL_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 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + // TODO: Retrieve PSK identity hint and callback to app + // + *p += len; + ret = 0; + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_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( ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret; + size_t len_bytes = ssl->minor_ver == SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + p[0] = (unsigned char) ssl->max_major_ver; + p[1] = (unsigned char) ssl->max_minor_ver; + + if( ( ret = ssl->f_rng( ssl->p_rng, p + 2, 46 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + + /* + * Now write it out, encrypted + */ + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, + POLARSSL_PK_RSA ) ) + { + SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = pk_encrypt( &ssl->session_negotiate->peer_cert->pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + SSL_MAX_CONTENT_LEN - offset - len_bytes, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_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 /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( ssl_context *ssl, + unsigned char **p, + unsigned char *end, + md_type_t *md_alg, + pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = POLARSSL_MD_NONE; + *pk_alg = POLARSSL_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = ssl_md_alg_from_hash( (*p)[0] ) ) == POLARSSL_MD_NONE ) + { + SSL_DEBUG_MSG( 2, ( "Server used unsupported " + "HashAlgorithm %d", *(p)[0] ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = ssl_pk_alg_from_sig( (*p)[1] ) ) == POLARSSL_PK_NONE ) + { + SSL_DEBUG_MSG( 2, ( "server used unsupported " + "SignatureAlgorithm %d", (*p)[1] ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); + SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( ssl_context *ssl ) +{ + int ret; + const ecp_keypair *peer_key; + + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, + POLARSSL_PK_ECKEY ) ) + { + SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = pk_ec( ssl->session_negotiate->peer_cert->pk ); + + if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + POLARSSL_ECDH_THEIRS ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_parse_server_key_exchange( ssl_context *ssl ) +{ + int ret; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + unsigned char *p, *end; +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + size_t sig_len, params_len; + unsigned char hash[64]; + md_type_t md_alg = POLARSSL_MD_NONE; + size_t hashlen; + pk_type_t pk_alg = POLARSSL_PK_NONE; +#endif + + SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_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] != SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + ssl->record_read = 1; + goto exit; + } + + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + p = ssl->in_msg + 4; + end = ssl->in_msg + ssl->in_hslen; + SSL_DEBUG_BUF( 3, "server key exchange", p, ssl->in_hslen - 4 ); + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTROUGH */ +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + params_len = p - ( ssl->in_msg + 4 ); + + /* + * Handle the digitally-signed structure + */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) + { + pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == POLARSSL_PK_ECDSA && md_alg == POLARSSL_MD_NONE ) + md_alg = POLARSSL_MD_SHA1; + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( end != p + sig_len ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( md_alg == POLARSSL_MD_NONE ) + { + md5_context md5; + sha1_context sha1; + + md5_init( &md5 ); + sha1_init( &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); + */ + md5_starts( &md5 ); + md5_update( &md5, ssl->handshake->randbytes, 64 ); + md5_update( &md5, ssl->in_msg + 4, params_len ); + md5_finish( &md5, hash ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); + sha1_update( &sha1, ssl->in_msg + 4, params_len ); + sha1_finish( &sha1, hash + 16 ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \ + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( md_alg != POLARSSL_MD_NONE ) + { + md_context_t ctx; + + 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 = md_init_ctx( &ctx, + md_info_from_type( md_alg ) ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "md_init_ctx", ret ); + return( ret ); + } + + md_starts( &ctx ); + md_update( &ctx, ssl->handshake->randbytes, 64 ); + md_update( &ctx, ssl->in_msg + 4, params_len ); + md_finish( &ctx, hash ); + md_free( &ctx ); + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( md_info_from_type( md_alg ) )->size ); + + /* + * Verify signature + */ + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "pk_verify", ret ); + return( ret ); + } + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +exit: + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_request( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_request( 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 ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + 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. + */ + if( ssl->record_read == 0 ) + { + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->record_read = 1; + } + + ssl->client_auth = 0; + ssl->state++; + + if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST ) + ssl->client_auth++; + + 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 + + buf = ssl->in_msg; + + // Retrieve cert types + // + cert_type_len = buf[4]; + n = cert_type_len; + + if( ssl->in_hslen < 6 + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + p = buf + 5; + while( cert_type_len > 0 ) + { +#if defined(POLARSSL_RSA_C) + if( *p == SSL_CERT_TYPE_RSA_SIGN && + pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_RSA ) ) + { + ssl->handshake->cert_type = SSL_CERT_TYPE_RSA_SIGN; + break; + } + else +#endif +#if defined(POLARSSL_ECDSA_C) + if( *p == SSL_CERT_TYPE_ECDSA_SIGN && + pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECDSA ) ) + { + ssl->handshake->cert_type = SSL_CERT_TYPE_ECDSA_SIGN; + break; + } + else +#endif + { + ; /* Unsupported cert type, ignore */ + } + + cert_type_len--; + p++; + } + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == 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[5 + n] << 8 ) + | ( buf[6 + n] ) ); + + p = buf + 7 + n; + m += 2; + n += sig_alg_len; + + if( ssl->in_hslen < 6 + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + } +#endif /* POLARSSL_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[5 + m + n] << 8 ) + | ( buf[6 + m + n] ) ); + + n += dn_len; + if( ssl->in_hslen != 7 + m + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +static int ssl_parse_server_hello_done( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ssl->record_read == 0 ) + { + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + ssl->record_read = 0; + + if( ssl->in_hslen != 4 || + ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( ssl_context *ssl ) +{ + int ret; + size_t i, n; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_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 = dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_make_public", ret ); + return( ret ); + } + + SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + ssl->handshake->pmslen = POLARSSL_PREMASTER_SIZE; + + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + &ssl->handshake->pmslen, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); + return( ret ); + } + + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + i = 4; + + ret = ecdh_make_public( &ssl->handshake->ecdh_ctx, + &n, + &ssl->out_msg[i], 1000, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_public", ret ); + return( ret ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + POLARSSL_MPI_MAX_SIZE, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( ret ); + } + + SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl->psk == NULL || ssl->psk_identity == NULL ) + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + + i = 4; + n = ssl->psk_identity_len; + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + memcpy( ssl->out_msg + i, ssl->psk_identity, ssl->psk_identity_len ); + i += ssl->psk_identity_len; + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) + { + n = 0; + } + else +#endif +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + n = ssl->handshake->dhm_ctx.len; + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + ret = dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * ClientECDiffieHellmanPublic public; + */ + ret = ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, + &ssl->out_msg[i], SSL_MAX_CONTENT_LEN - i, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_public", ret ); + return( ret ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) + { + i = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = i + n; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_verify( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_verify( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + const 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; + md_type_t md_alg = POLARSSL_MD_NONE; + unsigned int hashlen; + + SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || ssl_own_cert( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl_own_key( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make an RSA signature of the handshake digests + */ + ssl->handshake->calc_verify( ssl, hash ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != 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 = POLARSSL_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = POLARSSL_MD_SHA1; + } + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \ + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == 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 == + POLARSSL_MD_SHA384 ) + { + md_alg = POLARSSL_MD_SHA384; + ssl->out_msg[4] = SSL_HASH_SHA384; + } + else + { + md_alg = POLARSSL_MD_SHA256; + ssl->out_msg[4] = SSL_HASH_SHA256; + } + ssl->out_msg[5] = ssl_sig_from_pk( ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = pk_sign( ssl_own_key( ssl ), md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "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 = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( ssl_context *ssl ) +{ + int ret; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + + SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 0 handshake message type + * 1 . 3 handshake message length + * 4 . 7 ticket_lifetime_hint + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + if( ssl->in_msg[0] != SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 10 ) + { + SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + lifetime = ( ssl->in_msg[4] << 24 ) | ( ssl->in_msg[5] << 16 ) | + ( ssl->in_msg[6] << 8 ) | ( ssl->in_msg[7] ); + + ticket_len = ( ssl->in_msg[8] << 8 ) | ( ssl->in_msg[9] ); + + if( ticket_len + 10 != ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + 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; + + /* + * 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 ); + + polarssl_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + polarssl_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = polarssl_malloc( ticket_len ) ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "ticket malloc failed" ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + memcpy( ticket, ssl->in_msg + 10, 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." + */ + SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->length = 0; + + SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int ssl_handshake_client_step( ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + switch( ssl->state ) + { + case SSL_HELLO_REQUEST: + ssl->state = SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case SSL_SERVER_CERTIFICATE: + ret = ssl_parse_certificate( ssl ); + break; + + case SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case SSL_CLIENT_CERTIFICATE: + ret = ssl_write_certificate( ssl ); + break; + + case SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = ssl_write_change_cipher_spec( ssl ); + break; + + case SSL_CLIENT_FINISHED: + ret = ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_parse_new_session_ticket( ssl ); + else +#endif + ret = ssl_parse_change_cipher_spec( ssl ); + break; + + case SSL_SERVER_FINISHED: + ret = ssl_parse_finished( ssl ); + break; + + case SSL_FLUSH_BUFFERS: + SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = SSL_HANDSHAKE_WRAPUP; + break; + + case SSL_HANDSHAKE_WRAPUP: + ssl_handshake_wrapup( ssl ); + break; + + default: + SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* POLARSSL_SSL_CLI_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ssl_srv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ssl_srv.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,3628 @@ +/* + * SSLv3/TLSv1 server-side functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_SRV_C) + +#include "polarssl/debug.h" +#include "polarssl/ssl.h" + +#include <string.h> + +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(POLARSSL_HAVE_TIME) +#include <time.h> +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Serialize a session in the following format: + * 0 . n-1 session structure, n = sizeof(ssl_session) + * n . n+2 peer_cert length = m (0 if no certificate) + * n+3 . n+2+m peer cert ASN.1 + * + * Assumes ticket is NULL (always true on server side). + */ +static int ssl_save_session( const ssl_session *session, + unsigned char *buf, size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t left = buf_len; +#if defined(POLARSSL_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + if( left < sizeof( ssl_session ) ) + return( -1 ); + + memcpy( p, session, sizeof( ssl_session ) ); + p += sizeof( ssl_session ); + left -= sizeof( ssl_session ); + +#if defined(POLARSSL_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( -1 ); + + *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 /* POLARSSL_X509_CRT_PARSE_C */ + + *olen = p - buf; + + return( 0 ); +} + +/* + * Unserialise session, see ssl_save_session() + */ +static int ssl_load_session( ssl_session *session, + const unsigned char *buf, size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(POLARSSL_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + if( p + sizeof( ssl_session ) > end ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( session, p, sizeof( ssl_session ) ); + p += sizeof( ssl_session ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + if( p + 3 > end ) + return( POLARSSL_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( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = polarssl_malloc( sizeof( x509_crt ) ); + + if( session->peer_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + x509_crt_init( session->peer_cert ); + + if( ( ret = x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + x509_crt_free( session->peer_cert ); + polarssl_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + if( p != end ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Create session ticket, secured as recommended in RFC 5077 section 4: + * + * struct { + * opaque key_name[16]; + * opaque iv[16]; + * opaque encrypted_state<0..2^16-1>; + * opaque mac[32]; + * } ticket; + * + * (the internal state structure differs, however). + */ +static int ssl_write_ticket( ssl_context *ssl, size_t *tlen ) +{ + int ret; + unsigned char * const start = ssl->out_msg + 10; + unsigned char *p = start; + unsigned char *state; + unsigned char iv[16]; + size_t clear_len, enc_len, pad_len, i; + + *tlen = 0; + + if( ssl->ticket_keys == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + /* Write key name */ + memcpy( p, ssl->ticket_keys->key_name, 16 ); + p += 16; + + /* Generate and write IV (with a copy for aes_crypt) */ + if( ( ret = ssl->f_rng( ssl->p_rng, p, 16 ) ) != 0 ) + return( ret ); + memcpy( iv, p, 16 ); + p += 16; + + /* + * Dump session state + * + * After the session state itself, we still need room for 16 bytes of + * padding and 32 bytes of MAC, so there's only so much room left + */ + state = p + 2; + if( ssl_save_session( ssl->session_negotiate, state, + SSL_MAX_CONTENT_LEN - ( state - ssl->out_ctr ) - 48, + &clear_len ) != 0 ) + { + return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + SSL_DEBUG_BUF( 3, "session ticket cleartext", state, clear_len ); + + /* Apply PKCS padding */ + pad_len = 16 - clear_len % 16; + enc_len = clear_len + pad_len; + for( i = clear_len; i < enc_len; i++ ) + state[i] = (unsigned char) pad_len; + + /* Encrypt */ + if( ( ret = aes_crypt_cbc( &ssl->ticket_keys->enc, AES_ENCRYPT, + enc_len, iv, state, state ) ) != 0 ) + { + return( ret ); + } + + /* Write length */ + *p++ = (unsigned char)( ( enc_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( enc_len ) & 0xFF ); + p = state + enc_len; + + /* Compute and write MAC( key_name + iv + enc_state_len + enc_state ) */ + sha256_hmac( ssl->ticket_keys->mac_key, 16, start, p - start, p, 0 ); + p += 32; + + *tlen = p - start; + + SSL_DEBUG_BUF( 3, "session ticket structure", start, *tlen ); + + return( 0 ); +} + +/* + * Load session ticket (see ssl_write_ticket for structure) + */ +static int ssl_parse_ticket( ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + ssl_session session; + unsigned char *key_name = buf; + unsigned char *iv = buf + 16; + unsigned char *enc_len_p = iv + 16; + unsigned char *ticket = enc_len_p + 2; + unsigned char *mac; + unsigned char computed_mac[32]; + size_t enc_len, clear_len, i; + unsigned char pad_len, diff; + + SSL_DEBUG_BUF( 3, "session ticket structure", buf, len ); + + if( len < 34 || ssl->ticket_keys == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + mac = ticket + enc_len; + + if( len != enc_len + 66 ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + /* Check name, in constant time though it's not a big secret */ + diff = 0; + for( i = 0; i < 16; i++ ) + diff |= key_name[i] ^ ssl->ticket_keys->key_name[i]; + /* don't return yet, check the MAC anyway */ + + /* Check mac, with constant-time buffer comparison */ + sha256_hmac( ssl->ticket_keys->mac_key, 16, buf, len - 32, + computed_mac, 0 ); + + for( i = 0; i < 32; i++ ) + diff |= mac[i] ^ computed_mac[i]; + + /* Now return if ticket is not authentic, since we want to avoid + * decrypting arbitrary attacker-chosen data */ + if( diff != 0 ) + return( POLARSSL_ERR_SSL_INVALID_MAC ); + + /* Decrypt */ + if( ( ret = aes_crypt_cbc( &ssl->ticket_keys->dec, AES_DECRYPT, + enc_len, iv, ticket, ticket ) ) != 0 ) + { + return( ret ); + } + + /* Check PKCS padding */ + pad_len = ticket[enc_len - 1]; + + ret = 0; + for( i = 2; i < pad_len; i++ ) + if( ticket[enc_len - i] != pad_len ) + ret = POLARSSL_ERR_SSL_BAD_INPUT_DATA; + if( ret != 0 ) + return( ret ); + + clear_len = enc_len - pad_len; + + SSL_DEBUG_BUF( 3, "session ticket cleartext", ticket, clear_len ); + + /* Actually load session */ + if( ( ret = ssl_load_session( &session, ticket, clear_len ) ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "failed to parse ticket content" ) ); + ssl_session_free( &session ); + return( ret ); + } + +#if defined(POLARSSL_HAVE_TIME) + /* Check if still valid */ + if( (int) ( time( NULL) - session.start ) > ssl->ticket_lifetime ) + { + SSL_DEBUG_MSG( 1, ( "session ticket expired" ) ); + ssl_session_free( &session ); + return( POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED ); + } +#endif + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform him we're accepting the ticket (RFC 5077 section 3.4) + */ + session.length = ssl->session_negotiate->length; + memcpy( &session.id, ssl->session_negotiate->id, session.length ); + + ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + polarssl_zeroize( &session, sizeof( ssl_session ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +/* + * Wrapper around f_sni, allowing use of ssl_set_own_cert() but + * making it act on ssl->hanshake->sni_key_cert instead. + */ +static int ssl_sni_wrapper( ssl_context *ssl, + const unsigned char* name, size_t len ) +{ + int ret; + ssl_key_cert *key_cert_ori = ssl->key_cert; + + ssl->key_cert = NULL; + ret = ssl->f_sni( ssl->p_sni, ssl, name, len ); + ssl->handshake->sni_key_cert = ssl->key_cert; + + ssl->key_cert = key_cert_ori; + + return( ret ); +} + +static int ssl_parse_servername_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_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 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl_sni_wrapper( ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +static int ssl_parse_renegotiation_info( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation != 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 || + safer_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else +#endif /* POLARSSL_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \ + defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_parse_signature_algorithms_ext( 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 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_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 = md_list(); *md_cur != POLARSSL_MD_NONE; md_cur++ ) { + for( p = buf + 2; p < end; p += 2 ) { + if( *md_cur == (int) 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 */ + SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) ); + return( 0 ); + +have_sig_alg: + SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + ssl->handshake->sig_alg ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_TLS1_2 && + POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static int ssl_parse_supported_elliptic_curves( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const ecp_curve_info *curve_info, **curves; + + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_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 > POLARSSL_ECP_DP_MAX ) + our_size = POLARSSL_ECP_DP_MAX; + + if( ( curves = polarssl_malloc( our_size * sizeof( *curves ) ) ) == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + /* explicit void pointer cast for buggy MS compiler */ + memset( (void *) curves, 0, our_size * sizeof( *curves ) ); + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = 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( 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 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( list_size > 0 ) + { + if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED || + p[0] == POLARSSL_ECP_PF_COMPRESSED ) + { + ssl->handshake->ecdh_ctx.point_format = p[0]; + SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= SSL_MAX_FRAG_LEN_INVALID ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->encrypt_then_mac == SSL_ETM_ENABLED && + ssl->minor_ver != SSL_MINOR_VERSION_0 ) + { + ssl->session_negotiate->encrypt_then_mac = SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->extended_ms == SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != SSL_MINOR_VERSION_0 ) + { + ssl->handshake->extended_ms = SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ) + { + SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* POLARSSL_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl_parse_ticket( ssl, buf, len ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_parse_ticket", ret ); + return( 0 ); + } + + 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 /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_ALPN) +static int ssl_parse_alpn_ext( 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->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( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + /* + * Use our order of preference + */ + start = buf + 2; + end = buf + len; + for( ours = ssl->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( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cur_len = *theirs++; + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + return( POLARSSL_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 */ + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* POLARSSL_SSL_ALPN */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(POLARSSL_ECDSA_C) +static int ssl_check_key_curve( pk_context *pk, + const ecp_curve_info **curves ) +{ + const ecp_curve_info **crv = curves; + ecp_group_id grp_id = pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* POLARSSL_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( ssl_context *ssl, + const ssl_ciphersuite_t * ciphersuite_info ) +{ + ssl_key_cert *cur, *list, *fallback = NULL; + pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + int flags; + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->handshake->key_cert; + + if( pk_alg == POLARSSL_PK_NONE ) + return( 0 ); + + SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + for( cur = list; cur != NULL; cur = cur->next ) + { + SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! pk_can_do( cur->key, pk_alg ) ) + { + 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( ssl_check_cert_usage( cur->cert, ciphersuite_info, + SSL_IS_SERVER, &flags ) != 0 ) + { + SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(POLARSSL_ECDSA_C) + if( pk_alg == POLARSSL_PK_ECDSA && + ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) + { + 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 < SSL_MINOR_VERSION_3 && + cur->cert->sig_md != POLARSSL_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + 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 the is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* POLARSSL_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( ssl_context *ssl, int suite_id, + const ssl_ciphersuite_t **ciphersuite_info ) +{ + const ssl_ciphersuite_t *suite_info; + + suite_info = ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + 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 ) + { + SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + + if( ssl->arc4_disabled == SSL_ARC4_DISABLED && + suite_info->cipher == POLARSSL_CIPHER_ARC4_128 ) + { + SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); + return( 0 ); + } + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + if( ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(POLARSSL_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( ssl_ciphersuite_uses_psk( suite_info ) && + ssl->f_psk == NULL && + ( ssl->psk == NULL || ssl->psk_identity == NULL || + ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) ) + { + SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(POLARSSL_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 ) + { + SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +static int ssl_parse_client_hello_v2( 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 ssl_ciphersuite_t *ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* POLARSSL_SSL_RENEGOTIATION */ + + buf = ssl->in_hdr; + + SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + 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] != SSL_HS_CLIENT_HELLO || + buf[3] != SSL_MAJOR_VERSION_3 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->max_minor_ver ) + ? buf[4] : ssl->max_minor_ver; + + if( ssl->minor_ver < ssl->min_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->min_major_ver, ssl->min_minor_ver ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "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 + */ + 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]; + + 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 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->length = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->length ); + + 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] == SSL_EMPTY_RENEGOTIATION_INFO ) + { + SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* POLARSSL_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(POLARSSL_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && + p[1] == (unsigned char)( ( SSL_FALLBACK_SCSV >> 8 ) & 0xff ) && + p[2] == (unsigned char)( ( SSL_FALLBACK_SCSV ) & 0xff ) ) + { + SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->max_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* POLARSSL_SSL_FALLBACK_SCSV */ + + got_common_suite = 0; + ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(POLARSSL_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 ) + { + SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite_v2: + SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +static int ssl_parse_client_hello( ssl_context *ssl ) +{ + int ret, got_common_suite; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len; + unsigned int comp_len; + unsigned int ext_len = 0; + unsigned char *buf, *p, *ext; +#if defined(POLARSSL_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const ssl_ciphersuite_t *ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + +#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + if( ( buf[0] & 0x80 ) != 0 ) + return ssl_parse_client_hello_v2( ssl ); +#endif + + SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( buf[3] << 8 ) | buf[4] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]", + buf[1], buf[2] ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 4 message length + */ + + /* 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( buf[0] != SSL_MSG_HANDSHAKE || + buf[1] < SSL_MAJOR_VERSION_3 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( buf[3] << 8 ) | buf[4]; + + if( n < 45 || n > SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_msg; +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ) + n = ssl->in_msglen; + else +#endif + n = ssl->in_left - 5; + + ssl->handshake->update_checksum( ssl, buf, n ); + + /* + * SSL layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + * 38 . 38 session id length + * 39 . 38+x session id + * 39+x . 40+x ciphersuitelist length + * 41+x . 40+y ciphersuitelist + * 41+y . 41+y compression alg length + * 42+y . 41+z compression algs + * .. . .. extensions + */ + SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", + buf[0] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]", + buf[4], buf[5] ) ); + + /* + * Check the handshake type and protocol version + */ + if( buf[0] != SSL_HS_CLIENT_HELLO ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = buf[4]; + ssl->minor_ver = buf[5]; + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->min_major_ver || + ssl->minor_ver < ssl->min_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->min_major_ver, ssl->min_minor_ver ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->max_major_ver ) + { + ssl->major_ver = ssl->max_major_ver; + ssl->minor_ver = ssl->max_minor_ver; + } + else if( ssl->minor_ver > ssl->max_minor_ver ) + ssl->minor_ver = ssl->max_minor_ver; + + memcpy( ssl->handshake->randbytes, buf + 6, 32 ); + + /* + * Check the handshake message length + */ + if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check the session length + */ + sess_len = buf[38]; + + if( sess_len > 32 || sess_len > n - 42 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->length = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 39, + ssl->session_negotiate->length ); + + /* + * Check the ciphersuitelist length + */ + ciph_len = ( buf[39 + sess_len] << 8 ) + | ( buf[40 + sess_len] ); + + if( ciph_len < 2 || ( ciph_len % 2 ) != 0 || ciph_len > n - 42 - sess_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check the compression algorithms length + */ + comp_len = buf[41 + sess_len + ciph_len]; + + if( comp_len < 1 || comp_len > 16 || + comp_len > n - 42 - sess_len - ciph_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check the extension length + */ + if( n > 42 + sess_len + ciph_len + comp_len ) + { + ext_len = ( buf[42 + sess_len + ciph_len + comp_len] << 8 ) + | ( buf[43 + sess_len + ciph_len + comp_len] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + n != 44 + sess_len + ciph_len + comp_len + ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + SSL_DEBUG_BUF( 3, "Ext", buf + 44 + sess_len + ciph_len + comp_len, ext_len); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + ssl->session_negotiate->compression = SSL_COMPRESS_NULL; +#if defined(POLARSSL_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[42 + sess_len + ciph_len + i] == SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + SSL_DEBUG_BUF( 3, "client hello, random bytes", + buf + 6, 32 ); + SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 38, sess_len ); + SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 41 + sess_len, ciph_len ); + SSL_DEBUG_BUF( 3, "client hello, compression", + buf + 42 + sess_len + ciph_len, comp_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == SSL_EMPTY_RENEGOTIATION_INFO ) + { + SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + renegotiation_info_seen = 1; +#endif /* POLARSSL_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(POLARSSL_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == (unsigned char)( ( SSL_FALLBACK_SCSV >> 8 ) & 0xff ) && + p[1] == (unsigned char)( ( SSL_FALLBACK_SCSV ) & 0xff ) ) + { + SSL_DEBUG_MSG( 0, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->max_minor_ver ) + { + SSL_DEBUG_MSG( 0, ( "inapropriate fallback" ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* POLARSSL_SSL_FALLBACK_SCSV */ + + ext = buf + 44 + sess_len + ciph_len + comp_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 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + case TLS_EXT_SERVERNAME: + SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + + case TLS_EXT_RENEGOTIATION_INFO: + SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(POLARSSL_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) && \ + defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED) + case TLS_EXT_SIG_ALG: + SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_RENEGOTIATION ) + break; +#endif + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_PROTO_TLS1_2 && + POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + case TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + 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 TLS_EXT_SUPPORTED_POINT_FORMATS: + SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + case TLS_EXT_MAX_FRAGMENT_LENGTH: + SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + case TLS_EXT_TRUNCATED_HMAC: + SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + case TLS_EXT_ENCRYPT_THEN_MAC: + SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + case TLS_EXT_EXTENDED_MASTER_SECRET: + SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + case TLS_EXT_SESSION_TICKET: + SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_ALPN) + case TLS_EXT_ALPN: + SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + default: + 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 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != SSL_SECURE_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(POLARSSL_SSL_RENEGOTIATION) + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* POLARSSL_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_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->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 41 + sess_len; 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 + 41 + sess_len; 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 ) + { + SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + ssl_send_fatal_handshake_failure( ssl ); + return( POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + ssl_send_fatal_handshake_failure( ssl ); + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite: + SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + ssl->in_left = 0; + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const ssl_ciphersuite_t *suite = NULL; + const cipher_info_t *cipher = NULL; + + if( ssl->session_negotiate->encrypt_then_mac == SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == 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 = ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != POLARSSL_MODE_CBC ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation != 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; + + *olen = 5 + ssl->verify_data_len * 2; + } + else +#endif /* POLARSSL_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + + *olen = 5; + } +} + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static void ssl_write_supported_point_formats_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = POLARSSL_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_ALPN ) +static void ssl_write_alpn_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + 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)( ( TLS_EXT_ALPN >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( 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 /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +static int ssl_write_server_hello( ssl_context *ssl ) +{ +#if defined(POLARSSL_HAVE_TIME) + time_t t; +#endif + int ret; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + + if( ssl->f_rng == NULL ) + { + SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( POLARSSL_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; + + *p++ = (unsigned char) ssl->major_ver; + *p++ = (unsigned char) ssl->minor_ver; + + SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(POLARSSL_HAVE_TIME) + t = time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->f_rng( ssl->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* POLARSSL_HAVE_TIME */ + + if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + /* + * Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). + * If not, try looking up session ID in our cache. + */ + if( ssl->handshake->resume == 0 && +#if defined(POLARSSL_SSL_RENEGOTIATION) + ssl->renegotiation == SSL_INITIAL_HANDSHAKE && +#endif + ssl->session_negotiate->length != 0 && + ssl->f_get_cache != NULL && + ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) == 0 ) + { + 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(POLARSSL_HAVE_TIME) + ssl->session_negotiate->start = time( NULL ); +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->length = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->length = n = 32; + if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->length; + ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "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->length; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->length ); + p += ssl->session_negotiate->length; + + SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + 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 ); + + SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + ssl->session_negotiate->compression ) ); + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + 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 = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_SERVER_HELLO; + + ret = ssl_write_record( ssl ); + + SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_request( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_request( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + const 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 x509_crt *crt; + + SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ssl->authmode == SSL_VERIFY_NONE ) + { + 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(POLARSSL_RSA_C) + p[1 + ct_len++] = SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(POLARSSL_ECDSA_C) + p[1 + ct_len++] = SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(POLARSSL_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 == SSL_MINOR_VERSION_3 ) + { + /* + * Only use current running hash algorithm that is already required + * for requested ciphersuite. + */ + ssl->handshake->verify_sig_alg = SSL_HASH_SHA256; + + if( ssl->transform_negotiate->ciphersuite_info->mac == + POLARSSL_MD_SHA384 ) + { + ssl->handshake->verify_sig_alg = SSL_HASH_SHA384; + } + + /* + * Supported signature algorithms + */ +#if defined(POLARSSL_RSA_C) + p[2 + sa_len++] = ssl->handshake->verify_sig_alg; + p[2 + sa_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_ECDSA_C) + p[2 + sa_len++] = ssl->handshake->verify_sig_alg; + p[2 + sa_len++] = SSL_SIG_ECDSA; +#endif + + p[0] = (unsigned char)( sa_len >> 8 ); + p[1] = (unsigned char)( sa_len ); + sa_len += 2; + p += sa_len; + } +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + crt = ssl->ca_chain; + + total_dn_size = 0; + while( crt != NULL && crt->version != 0 ) + { + if( p - buf > 4096 ) + break; + + dn_size = crt->subject_raw.len; + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + SSL_DEBUG_BUF( 3, "requested DN", p, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = 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 = ssl_write_record( ssl ); + + SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( ssl_context *ssl ) +{ + int ret; + + if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECKEY ) ) + { + SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx, + pk_ec( *ssl_own_key( ssl ) ), + POLARSSL_ECDH_OURS ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_write_server_key_exchange( ssl_context *ssl ) +{ + int ret; + size_t n = 0; + const ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_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); +#endif + + SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + ssl_get_ecdh_params_from_cert( ssl ); + + SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* TODO: Support identity hints */ + *(p++) = 0x00; + *(p++) = 0x00; + + n += 2; + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + /* + * 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 = mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->dhm_P ) ) != 0 || + ( ret = mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->dhm_G ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_copy", ret ); + return( ret ); + } + + if( ( ret = dhm_make_params( &ssl->handshake->dhm_ctx, + (int) mpi_size( &ssl->handshake->dhm_ctx.P ), + p, &len, ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_make_params", ret ); + return( ret ); + } + + dig_signed = p; + dig_signed_len = len; + + p += len; + n += len; + + SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const ecp_curve_info **curve = NULL; +#if defined(POLARSSL_SSL_SET_CURVES) + const ecp_group_id *gid; + + /* Match our preference list against the offered curves */ + for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: +#else + curve = ssl->handshake->curves; +#endif + + if( *curve == NULL ) + { + SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp, + (*curve)->grp_id ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret ); + return( ret ); + } + + if( ( ret = ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, + p, SSL_MAX_CONTENT_LEN - n, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_params", ret ); + return( ret ); + } + + dig_signed = p; + dig_signed_len = len; + + p += len; + n += len; + + SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + } +#endif /* POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + size_t signature_len = 0; + unsigned int hashlen = 0; + unsigned char hash[64]; + md_type_t md_alg = POLARSSL_MD_NONE; + + /* + * Choose hash algorithm. NONE means MD5 + SHA1 here. + */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg ); + + if( md_alg == POLARSSL_MD_NONE ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + md_alg = POLARSSL_MD_SHA1; + } + else +#endif + { + md_alg = POLARSSL_MD_NONE; + } + + /* + * Compute the hash to be signed + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( md_alg == POLARSSL_MD_NONE ) + { + md5_context md5; + sha1_context sha1; + + md5_init( &md5 ); + sha1_init( &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); + */ + md5_starts( &md5 ); + md5_update( &md5, ssl->handshake->randbytes, 64 ); + md5_update( &md5, dig_signed, dig_signed_len ); + md5_finish( &md5, hash ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); + sha1_update( &sha1, dig_signed, dig_signed_len ); + sha1_finish( &sha1, hash + 16 ); + + hashlen = 36; + + md5_free( &md5 ); + sha1_free( &sha1 ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \ + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( md_alg != POLARSSL_MD_NONE ) + { + md_context_t ctx; + const md_info_t *md_info = md_info_from_type( md_alg ); + + 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 = md_init_ctx( &ctx, md_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "md_init_ctx", ret ); + return( ret ); + } + + md_starts( &ctx ); + md_update( &ctx, ssl->handshake->randbytes, 64 ); + md_update( &ctx, dig_signed, dig_signed_len ); + md_finish( &ctx, hash ); + md_free( &ctx ); + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( md_info_from_type( md_alg ) )->size ); + + /* + * Make the signature + */ + if( ssl_own_key( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + *(p++) = ssl->handshake->sig_alg; + *(p++) = ssl_sig_from_pk( ssl_own_key( ssl ) ); + + n += 2; + } +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + if( ( ret = pk_sign( ssl_own_key( ssl ), md_alg, hash, hashlen, + p + 2 , &signature_len, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "pk_sign", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( signature_len >> 8 ); + *(p++) = (unsigned char)( signature_len ); + n += 2; + + SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); + + p += signature_len; + n += signature_len; + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || + POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + + ssl->out_msglen = 4 + n; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + + return( 0 ); +} + +static int ssl_write_server_hello_done( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_read_public", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +static int ssl_parse_encrypted_pms( ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + size_t len = pk_get_len( ssl_own_key( ssl ) ); + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, diff, peer_pmslen; + + if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_RSA ) ) + { + SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Decrypt the premaster using own private RSA key + */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) + { + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + /* + * 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->f_rng( ssl->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + return( ret ); + + ret = pk_decrypt( ssl_own_key( ssl ), p, len, + peer_pms, &peer_pmslen, + sizeof( peer_pms ), + ssl->f_rng, ssl->p_rng ); + + diff = (size_t) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ssl->handshake->max_major_ver; + diff |= peer_pms[1] ^ ssl->handshake->max_minor_ver; + +#if defined(POLARSSL_SSL_DEBUG_ALL) + if( diff != 0 ) + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + mask = ( diff | - diff ) >> ( sizeof( size_t ) * 8 - 1 ); + mask = (unsigned char)( - ( ret != 0 ) ); /* mask = diff ? 0xff : 0x00 */ + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_client_psk_identity( ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + size_t n; + + if( ssl->f_psk == NULL && + ( ssl->psk == NULL || ssl->psk_identity == NULL || + ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) ) + { + SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( *p + 2 > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n < 1 || n > 65535 || *p + n > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->f_psk != NULL ) + { + if( ssl->f_psk( ssl->p_psk, ssl, *p, n ) != 0 ) + ret = POLARSSL_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->psk_identity_len || + safer_memcmp( ssl->psk_identity, *p, n ) != 0 ) + { + ret = POLARSSL_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == POLARSSL_ERR_SSL_UNKNOWN_IDENTITY ) + { + SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 ) + { + return( ret ); + } + + return( POLARSSL_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( ssl_context *ssl ) +{ + int ret; + const ssl_ciphersuite_t *ciphersuite_info; + + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + ssl->handshake->pmslen = POLARSSL_PREMASTER_SIZE; + + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + &ssl->handshake->pmslen, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx, + ssl->in_msg + 4, ssl->in_hslen - 4 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_read_public", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + POLARSSL_MPI_MAX_SIZE, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_read_public", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, + ssl->in_msg + 4, + ssl->in_msg + ssl->in_hslen, + 0 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_verify( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_verify( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t sa_len, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + pk_type_t pk_alg; +#endif + md_type_t md_alg; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->session_negotiate->peer_cert == NULL ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + ssl->handshake->calc_verify( ssl, hash ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + ssl->state++; + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 sig alg (TLS 1.2 only) + * 4+n . 5+n signature length (n = sa_len) + * 6+n . 6+n+m signature (m = sig_len) + */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) + { + sa_len = 0; + + md_alg = POLARSSL_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( pk_can_do( &ssl->session_negotiate->peer_cert->pk, + POLARSSL_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = POLARSSL_MD_SHA1; + } + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + sa_len = 2; + + /* + * Hash + */ + if( ssl->in_msg[4] != ssl->handshake->verify_sig_alg ) + { + SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + md_alg = ssl_md_alg_from_hash( ssl->handshake->verify_sig_alg ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + + /* + * Signature + */ + if( ( pk_alg = ssl_pk_alg_from_sig( ssl->in_msg[5] ) ) + == POLARSSL_PK_NONE ) + { + SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + sig_len = ( ssl->in_msg[4 + sa_len] << 8 ) | ssl->in_msg[5 + sa_len]; + + if( sa_len + sig_len + 6 != ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash_start, hashlen, + ssl->in_msg + 6 + sa_len, sig_len ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "pk_verify", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( ssl_context *ssl ) +{ + int ret; + size_t tlen; + uint32_t lifetime = (uint32_t) ssl->ticket_lifetime; + + SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = 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 + */ + + 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; + + if( ( ret = ssl_write_ticket( ssl, &tlen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_ticket", ret ); + tlen = 0; + } + + 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 = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int ssl_handshake_server_step( ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + switch( ssl->state ) + { + case SSL_HELLO_REQUEST: + ssl->state = SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case SSL_SERVER_CERTIFICATE: + ret = ssl_write_certificate( ssl ); + break; + + case SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case SSL_CLIENT_CERTIFICATE: + ret = ssl_parse_certificate( ssl ); + break; + + case SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = ssl_parse_change_cipher_spec( ssl ); + break; + + case SSL_CLIENT_FINISHED: + ret = ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = ssl_write_change_cipher_spec( ssl ); + break; + + case SSL_SERVER_FINISHED: + ret = ssl_write_finished( ssl ); + break; + + case SSL_FLUSH_BUFFERS: + SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = SSL_HANDSHAKE_WRAPUP; + break; + + case SSL_HANDSHAKE_WRAPUP: + ssl_handshake_wrapup( ssl ); + break; + + default: + SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* POLARSSL_SSL_SRV_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/ssl_tls.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/ssl_tls.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,5292 @@ +/* + * SSLv3/TLSv1 shared functions + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_TLS_C) + +#include "polarssl/debug.h" +#include "polarssl/ssl.h" + +#include <string.h> + +#if defined(POLARSSL_X509_CRT_PARSE_C) && \ + defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) +#include "polarssl/oid.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_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[SSL_MAX_FRAG_LEN_INVALID] = +{ + SSL_MAX_CONTENT_LEN, /* SSL_MAX_FRAG_LEN_NONE */ + 512, /* SSL_MAX_FRAG_LEN_512 */ + 1024, /* SSL_MAX_FRAG_LEN_1024 */ + 2048, /* SSL_MAX_FRAG_LEN_2048 */ + 4096, /* SSL_MAX_FRAG_LEN_4096 */ +}; +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +static int ssl_session_copy( ssl_session *dst, const ssl_session *src ) +{ + ssl_session_free( dst ); + memcpy( dst, src, sizeof( ssl_session ) ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + if( src->peer_cert != NULL ) + { + int ret; + + dst->peer_cert = polarssl_malloc( sizeof(x509_crt) ); + if( dst->peer_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + x509_crt_init( dst->peer_cert ); + + if( ( ret = x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + polarssl_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( src->ticket != NULL ) + { + dst->ticket = polarssl_malloc( src->ticket_len ); + if( dst->ticket == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + return( 0 ); +} + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) +int (*ssl_hw_record_init)( 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 (*ssl_hw_record_activate)( ssl_context *ssl, int direction) = NULL; +int (*ssl_hw_record_reset)( ssl_context *ssl ) = NULL; +int (*ssl_hw_record_write)( ssl_context *ssl ) = NULL; +int (*ssl_hw_record_read)( ssl_context *ssl ) = NULL; +int (*ssl_hw_record_finish)( ssl_context *ssl ) = NULL; +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + +/* + * Key material generation + */ +#if defined(POLARSSL_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; + md5_context md5; + sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + md5_init( &md5 ); + 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 ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, padding, 1 + i ); + sha1_update( &sha1, secret, slen ); + sha1_update( &sha1, random, rlen ); + sha1_finish( &sha1, sha1sum ); + + md5_starts( &md5 ); + md5_update( &md5, secret, slen ); + md5_update( &md5, sha1sum, 20 ); + md5_finish( &md5, dstbuf + i * 16 ); + } + + md5_free( &md5 ); + sha1_free( &sha1 ); + + polarssl_zeroize( padding, sizeof( padding ) ); + polarssl_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_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]; + + if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) + return( POLARSSL_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] + */ + md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp ); + + for( i = 0; i < dlen; i += 16 ) + { + md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i ); + md5_hmac( S1, hs, 4 + tmp, 16, 4 + tmp ); + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + sha1_hmac( S2, hs, tmp + 20, nb, tmp ); + + for( i = 0; i < dlen; i += 20 ) + { + sha1_hmac( S2, hs, tmp, 20 + nb, h_i ); + sha1_hmac( S2, hs, tmp, 20, 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] ); + } + + polarssl_zeroize( tmp, sizeof( tmp ) ); + polarssl_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_TLS1) || POLARSSL_SSL_PROTO_TLS1_1 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_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 ) +{ + size_t nb; + size_t i, j, k; + unsigned char tmp[128]; + unsigned char h_i[32]; + + if( sizeof( tmp ) < 32 + strlen( label ) + rlen ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + 32, label, nb ); + memcpy( tmp + 32 + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_<hash>(secret, label + random)[0..dlen] + */ + sha256_hmac( secret, slen, tmp + 32, nb, tmp, 0 ); + + for( i = 0; i < dlen; i += 32 ) + { + sha256_hmac( secret, slen, tmp, 32 + nb, h_i, 0 ); + sha256_hmac( secret, slen, tmp, 32, tmp, 0 ); + + k = ( i + 32 > dlen ) ? dlen % 32 : 32; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + polarssl_zeroize( tmp, sizeof( tmp ) ); + polarssl_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_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 ) +{ + size_t nb; + size_t i, j, k; + unsigned char tmp[128]; + unsigned char h_i[48]; + + if( sizeof( tmp ) < 48 + strlen( label ) + rlen ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + 48, label, nb ); + memcpy( tmp + 48 + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_<hash>(secret, label + random)[0..dlen] + */ + sha512_hmac( secret, slen, tmp + 48, nb, tmp, 1 ); + + for( i = 0; i < dlen; i += 48 ) + { + sha512_hmac( secret, slen, tmp, 48 + nb, h_i, 1 ); + sha512_hmac( secret, slen, tmp, 48, tmp, 1 ); + + k = ( i + 48 > dlen ) ? dlen % 48 : 48; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + polarssl_zeroize( tmp, sizeof( tmp ) ); + polarssl_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( ssl_context *, const unsigned char *, size_t ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(POLARSSL_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( ssl_context *, unsigned char * ); +static void ssl_calc_finished_ssl( ssl_context *, unsigned char *, int ); +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls( ssl_context *, unsigned char *, int ); +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +static void ssl_update_checksum_sha256( ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( ssl_context *,unsigned char * ); +static void ssl_calc_finished_tls_sha256( ssl_context *,unsigned char *, int ); +#endif + +#if defined(POLARSSL_SHA512_C) +static void ssl_update_checksum_sha384( ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls_sha384( ssl_context *, unsigned char *, int ); +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +int ssl_derive_keys( 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 cipher_info_t *cipher_info; + const md_info_t *md_info; + + ssl_session *session = ssl->session_negotiate; + ssl_transform *transform = ssl->transform_negotiate; + ssl_handshake_params *handshake = ssl->handshake; + + SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + cipher_info = cipher_info_from_type( transform->ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", + transform->ciphersuite_info->cipher ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = md_info_from_type( transform->ciphersuite_info->mac ); + if( md_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "md info for %d not found", + transform->ciphersuite_info->mac ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == 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(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < 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(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA512_C) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 && + transform->ciphersuite_info->mac == POLARSSL_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(POLARSSL_SHA256_C) + if( ssl->minor_ver == 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 /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_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 ) + { + SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, + handshake->pmslen ); + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_ENABLED ) + { + unsigned char session_hash[48]; + size_t hash_len; + + SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + + ssl->handshake->calc_verify( ssl, session_hash ); + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { +#if defined(POLARSSL_SHA512_C) + if( ssl->transform_negotiate->ciphersuite_info->mac == + POLARSSL_MD_SHA384 ) + { + hash_len = 48; + } + else +#endif + hash_len = 32; + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + hash_len = 36; + + SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); + + handshake->tls_prf( handshake->premaster, handshake->pmslen, + "extended master secret", + session_hash, hash_len, session->master, 48 ); + + } + else +#endif + handshake->tls_prf( handshake->premaster, handshake->pmslen, + "master secret", + handshake->randbytes, 64, session->master, 48 ); + + + polarssl_zeroize( handshake->premaster, sizeof(handshake->premaster) ); + } + else + 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 ); + polarssl_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 ) + */ + handshake->tls_prf( session->master, 48, "key expansion", + handshake->randbytes, 64, keyblk, 256 ); + + SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + ssl_get_ciphersuite_name( session->ciphersuite ) ) ); + SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); + SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + polarssl_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + transform->keylen = cipher_info->key_length / 8; + + if( cipher_info->mode == POLARSSL_MODE_GCM || + cipher_info->mode == POLARSSL_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 & + POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + } + else + { + int ret; + + /* Initialize HMAC contexts */ + if( ( ret = md_init_ctx( &transform->md_ctx_enc, md_info ) ) != 0 || + ( ret = md_init_ctx( &transform->md_ctx_dec, md_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "md_init_ctx", ret ); + return( ret ); + } + + /* Get MAC length */ + transform->maclen = md_get_size( md_info ); + +#if defined(POLARSSL_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 == SSL_TRUNC_HMAC_ENABLED ) + transform->maclen = SSL_TRUNCATED_HMAC_LEN; +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == POLARSSL_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(POLARSSL_SSL_ENCRYPT_THEN_MAC) + if( session->encrypt_then_mac == 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(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 || + ssl->minor_ver == SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_2 || + ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + } + + 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(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == 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 /* POLARSSL_SSL_CLI_C */ +#if defined(POLARSSL_SSL_SRV_C) + if( ssl->endpoint == 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 /* POLARSSL_SSL_SRV_C */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + if( transform->maclen > sizeof transform->mac_enc ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->mac_enc, mac_enc, transform->maclen ); + memcpy( transform->mac_dec, mac_dec, transform->maclen ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 ) + { + md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); + md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_init != NULL ) + { + int ret = 0; + + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_init()" ) ); + + if( ( ret = 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 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_init", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + + if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_init_ctx", ret ); + return( ret ); + } + + if( ( ret = cipher_init_ctx( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_init_ctx", ret ); + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_length, + POLARSSL_ENCRYPT ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_setkey", ret ); + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_length, + POLARSSL_DECRYPT ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_setkey", ret ); + return( ret ); + } + +#if defined(POLARSSL_CIPHER_MODE_CBC) + if( cipher_info->mode == POLARSSL_MODE_CBC ) + { + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_enc, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret ); + return( ret ); + } + + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_dec, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret ); + return( ret ); + } + } +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + polarssl_zeroize( keyblk, sizeof( keyblk ) ); + +#if defined(POLARSSL_ZLIB_SUPPORT) + // Initialize compression + // + if( session->compression == SSL_COMPRESS_DEFLATE ) + { + if( ssl->compress_buf == NULL ) + { + SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = polarssl_malloc( SSL_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", + SSL_BUFFER_LEN ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + } + + 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 ) + { + SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); + } + } +#endif /* POLARSSL_ZLIB_SUPPORT */ + + SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] ) +{ + md5_context md5; + sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + md5_update( &md5, ssl->session_negotiate->master, 48 ); + md5_update( &md5, pad_1, 48 ); + md5_finish( &md5, hash ); + + md5_starts( &md5 ); + md5_update( &md5, ssl->session_negotiate->master, 48 ); + md5_update( &md5, pad_2, 48 ); + md5_update( &md5, hash, 16 ); + md5_finish( &md5, hash ); + + sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + sha1_update( &sha1, pad_1, 40 ); + sha1_finish( &sha1, hash + 16 ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + sha1_update( &sha1, pad_2, 40 ); + sha1_update( &sha1, hash + 16, 20 ); + sha1_finish( &sha1, hash + 16 ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + return; +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] ) +{ + md5_context md5; + sha1_context sha1; + + SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + md5_finish( &md5, hash ); + sha1_finish( &sha1, hash + 16 ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + return; +} +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] ) +{ + sha256_context sha256; + + SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + memcpy( &sha256, &ssl->handshake->fin_sha256, sizeof(sha256_context) ); + sha256_finish( &sha256, hash ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + sha256_free( &sha256 ); + + return; +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) +void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] ) +{ + sha512_context sha512; + + SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + memcpy( &sha512, &ssl->handshake->fin_sha512, sizeof(sha512_context) ); + sha512_finish( &sha512, hash ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + sha512_free( &sha512 ); + + return; +} +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + + /* + * 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(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 + (int) ssl->psk_len ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + p += ssl->psk_len; + } + else +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == POLARSSL_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 /* POLARSSL_KEY_EXCHANGE_RSA_PKS_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + int ret; + size_t len = end - ( p + 2 ); + + /* Write length only when we know the actual value */ + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, &len, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); + return( ret ); + } + *(p++) = (unsigned char)( len >> 8 ); + *(p++) = (unsigned char)( len ); + p += len; + + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret; + size_t zlen; + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( zlen >> 8 ); + *(p++) = (unsigned char)( zlen ); + p += zlen; + + SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 + (int) ssl->psk_len ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + memcpy( p, ssl->psk, ssl->psk_len ); + p += ssl->psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) +/* + * SSLv3.0 MAC functions + */ +static void ssl_mac( 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 = md_get_size( md_ctx->md_info ); + int md_type = md_get_type( md_ctx->md_info ); + + /* Only MD5 and SHA-1 supported */ + if( md_type == POLARSSL_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 ); + md_starts( md_ctx ); + md_update( md_ctx, secret, md_size ); + md_update( md_ctx, padding, padlen ); + md_update( md_ctx, header, 11 ); + md_update( md_ctx, buf, len ); + md_finish( md_ctx, buf + len ); + + memset( padding, 0x5C, padlen ); + md_starts( md_ctx ); + md_update( md_ctx, secret, md_size ); + md_update( md_ctx, padding, padlen ); + md_update( md_ctx, buf + len, md_size ); + md_finish( md_ctx, buf + len ); +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \ + ( defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) ) +#define POLARSSL_SOME_MODES_USE_MAC +#endif + +/* + * Encryption/decryption functions + */ +static int ssl_encrypt_buf( ssl_context *ssl ) +{ + size_t i; + cipher_mode_t mode; + int auth_done = 0; + + SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( ssl->session_out == NULL || ssl->transform_out == NULL ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + mode = cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); + + SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + /* + * Add MAC before if needed + */ +#if defined(POLARSSL_SOME_MODES_USE_MAC) + if( mode == POLARSSL_MODE_STREAM || + ( mode == POLARSSL_MODE_CBC +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + && ssl->session_out->encrypt_then_mac == SSL_ETM_DISABLED +#endif + ) ) + { +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == 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(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 ) + { + md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 ); + md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_msg, ssl->out_msglen ); + md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_msg + ssl->out_msglen ); + md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + 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(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) + if( mode == POLARSSL_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + if( ( ret = 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 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( ssl->out_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */ +#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C) + if( mode == POLARSSL_MODE_GCM || + mode == POLARSSL_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 & + POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + memcpy( add_data, ssl->out_ctr, 8 ); + add_data[8] = ssl->out_msgtype; + add_data[9] = ssl->major_ver; + add_data[10] = ssl->minor_ver; + add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->out_msglen & 0xFF; + + SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + /* + * Generate IV + */ +#if defined(POLARSSL_SSL_AEAD_RANDOM_IV) + ret = ssl->f_rng( ssl->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 */ + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_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 + + 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; + + SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + /* + * Encrypt and authenticate + */ + if( ( ret = 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 ) + { + SSL_DEBUG_RET( 1, "cipher_auth_encrypt", ret ); + return( ret ); + } + + if( olen != enc_msglen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen += taglen; + auth_done++; + + SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); + } + else +#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */ +#if defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) + if( mode == POLARSSL_MODE_CBC ) + { + int ret; + unsigned char *enc_msg; + size_t enc_msglen, padlen, olen = 0; + + 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(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_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 >= SSL_MINOR_VERSION_2 ) + { + /* + * Generate IV + */ + int ret = ssl->f_rng( ssl->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 /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */ + + 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 = 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 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( enc_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver < 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(POLARSSL_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]; + + 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 ); + + SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); + md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_iv, ssl->out_msglen ); + md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_iv + ssl->out_msglen ); + md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + for( i = 8; i > 0; i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loops goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( POLARSSL_ERR_SSL_COUNTER_WRAPPING ); + } + + SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +#define POLARSSL_SSL_MAX_MAC_SIZE 48 + +static int ssl_decrypt_buf( ssl_context *ssl ) +{ + size_t i; + cipher_mode_t mode; + int auth_done = 0; +#if defined(POLARSSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + + SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + + if( ssl->session_in == NULL || ssl->transform_in == NULL ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + mode = cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); + + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", + ssl->in_msglen, ssl->transform_in->minlen ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) + if( mode == POLARSSL_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + padlen = 0; + + if( ( ret = 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 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( ssl->in_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */ +#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C) + if( mode == POLARSSL_MODE_GCM || + mode == POLARSSL_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 & + POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16; + unsigned char explicit_iv_len = ssl->transform_in->ivlen - + ssl->transform_in->fixed_ivlen; + + if( ssl->in_msglen < (size_t) explicit_iv_len + taglen ) + { + SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " + "+ taglen (%d)", ssl->in_msglen, + explicit_iv_len, taglen ) ); + return( POLARSSL_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; + add_data[9] = ssl->major_ver; + add_data[10] = ssl->minor_ver; + add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->in_msglen & 0xFF; + + 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 ); + + SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ); + SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = 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 ) + { + SSL_DEBUG_RET( 1, "cipher_auth_decrypt", ret ); + + if( ret == POLARSSL_ERR_CIPHER_AUTH_FAILED ) + return( POLARSSL_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + if( olen != dec_msglen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */ +#if defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) + if( mode == POLARSSL_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(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= 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 ) + { + 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( POLARSSL_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(POLARSSL_SSL_ENCRYPT_THEN_MAC) + if( ssl->session_in->encrypt_then_mac == SSL_ETM_ENABLED ) + { + unsigned char computed_mac[POLARSSL_SSL_MAX_MAC_SIZE]; + unsigned char pseudo_hdr[13]; + + 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 ); + + SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); + md_hmac_update( &ssl->transform_in->md_ctx_dec, + ssl->in_iv, ssl->in_msglen ); + md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac ); + md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, + ssl->transform_in->maclen ); + SSL_DEBUG_BUF( 4, "computed mac", computed_mac, + ssl->transform_in->maclen ); + + if( safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac, + ssl->transform_in->maclen ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + auth_done++; + } +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) + { + SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + ssl->in_msglen, ssl->transform_in->ivlen ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + +#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( ssl->minor_ver >= 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 /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */ + + if( ( ret = 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 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( dec_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver < 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(POLARSSL_SSL_DEBUG_ALL) + 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(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + if( padlen > ssl->transform_in->ivlen ) + { +#if defined(POLARSSL_SSL_DEBUG_ALL) + 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 /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > 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 >= 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 < 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(POLARSSL_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= correct * 0x1FF; + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_msglen -= padlen; + } + else +#endif /* POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + 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(POLARSSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE]; + + ssl->in_msglen -= ssl->transform_in->maclen; + + ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); + + memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == 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 /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > 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; + + md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 13 ); + md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, + ssl->in_msglen ); + md_hmac_finish( &ssl->transform_in->md_ctx_dec, + ssl->in_msg + ssl->in_msglen ); + /* Call md_process at least once due to cache attacks */ + for( j = 0; j < extra_run + 1; j++ ) + md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); + + md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); + SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + + if( safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ) != 0 ) + { +#if defined(POLARSSL_SSL_DEBUG_ALL) + SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } +#endif /* POLARSSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_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 ) + { + SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + + for( i = 8; i > 0; i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loops goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( POLARSSL_ERR_SSL_COUNTER_WRAPPING ); + } + + SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(POLARSSL_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( 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; + + SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + 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 = SSL_BUFFER_LEN; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = SSL_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out; + + SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( 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; + + SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + 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 = SSL_MAX_CONTENT_LEN; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = SSL_MAX_CONTENT_LEN - + ssl->transform_in->ctx_inflate.avail_out; + + SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* POLARSSL_ZLIB_SUPPORT */ + +/* + * Fill the input message buffer + */ +int ssl_fetch_input( ssl_context *ssl, size_t nb_want ) +{ + int ret; + size_t len; + + SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( nb_want > SSL_BUFFER_LEN - 8 ) + { + SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len ); + + SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + SSL_DEBUG_RET( 2, "ssl->f_recv", ret ); + + if( ret == 0 ) + return( POLARSSL_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + ssl->in_left += ret; + } + + SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int ssl_flush_output( ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + + SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + while( ssl->out_left > 0 ) + { + SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + 5 + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr + 5 + ssl->out_msglen - ssl->out_left; + ret = ssl->f_send( ssl->p_send, buf, ssl->out_left ); + + SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + ssl->out_left -= ret; + } + + SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ +int ssl_write_record( ssl_context *ssl ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + + SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + + if( ssl->out_msgtype == SSL_MSG_HANDSHAKE ) + { + 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 ) ); + + if( ssl->out_msg[0] != SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + } + +#if defined(POLARSSL_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*POLARSSL_ZLIB_SUPPORT */ + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_write != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_write()" ) ); + + ret = ssl_hw_record_write( ssl ); + if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_write", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + ssl->out_hdr[1] = (unsigned char) ssl->major_ver; + ssl->out_hdr[2] = (unsigned char) ssl->minor_ver; + ssl->out_hdr[3] = (unsigned char)( len >> 8 ); + ssl->out_hdr[4] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + ssl->out_hdr[3] = (unsigned char)( len >> 8 ); + ssl->out_hdr[4] = (unsigned char)( len ); + } + + ssl->out_left = 5 + ssl->out_msglen; + + 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_hdr[3] << 8 ) | ssl->out_hdr[4] ) ); + + SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, 5 + ssl->out_msglen ); + } + + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +int ssl_read_record( ssl_context *ssl ) +{ + int ret, done = 0; + + 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 ); + + ssl->in_hslen = 4; + ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3]; + + SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + + if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msglen < ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->state != SSL_HANDSHAKE_OVER ) + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + + return( 0 ); + } + + ssl->in_hslen = 0; + + /* + * Read the record header and validate it + */ + if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + + ssl->in_msgtype = ssl->in_hdr[0]; + ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4]; + + SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2], + ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) ); + + if( ssl->in_hdr[1] != ssl->major_ver ) + { + SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_hdr[2] > ssl->max_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + /* Sanity check (outer boundaries) */ + if( ssl->in_msglen < 1 || ssl->in_msglen > SSL_BUFFER_LEN - 13 ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + /* + * Make sure the message length is acceptable for the current transform + * and protocol version. + */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen > SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + SSL_MAX_CONTENT_LEN + 256 ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } +#endif + } + + /* + * Read and optionally decrypt the message contents + */ + if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + + SSL_DEBUG_BUF( 4, "input record from network", + ssl->in_hdr, 5 + ssl->in_msglen ); + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_read != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_read()" ) ); + + ret = ssl_hw_record_read( ssl ); + if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_read", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) + { +#if defined(POLARSSL_SSL_ALERT_MESSAGES) + if( ret == POLARSSL_ERR_SSL_INVALID_MAC ) + { + ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + return( ret ); + } + + SSL_DEBUG_BUF( 4, "input payload after decrypt", + ssl->in_msg, ssl->in_msglen ); + + if( ssl->in_msglen > SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + } + +#if defined(POLARSSL_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + + ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); + } +#endif /* POLARSSL_ZLIB_SUPPORT */ + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE && + ssl->in_msgtype != SSL_MSG_ALERT && + ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) + { + SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) + { + return( ret ); + } + + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msgtype == SSL_MSG_HANDSHAKE ) + { + ssl->in_hslen = 4; + ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3]; + + SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + + /* + * Additional checks to validate the handshake header + */ + if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msglen < ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->state != SSL_HANDSHAKE_OVER ) + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + if( ssl->in_msgtype == SSL_MSG_ALERT ) + { + 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 + */ + if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL ) + { + SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + } + + ssl->in_left = 0; + + SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +int ssl_send_fatal_handshake_failure( ssl_context *ssl ) +{ + int ret; + + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int ssl_send_alert_message( ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + + ssl->out_msgtype = SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +/* + * Handshake functions + */ +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +int ssl_write_certificate( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} + +int ssl_parse_certificate( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +int ssl_write_certificate( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const x509_crt *crt; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = SSL_MSG_ALERT; + ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT; + + SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + } +#endif /* POLARSSL_SSL_CLI_C */ +#if defined(POLARSSL_SSL_SRV_C) + if( ssl->endpoint == SSL_IS_SERVER ) + { + if( ssl_own_cert( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } +#endif + + SSL_DEBUG_CRT( 3, "own certificate", 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 = ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > SSL_MAX_CONTENT_LEN - 3 - i ) + { + SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, SSL_MAX_CONTENT_LEN ) ); + return( POLARSSL_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 = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CERTIFICATE; + +#if defined(POLARSSL_SSL_PROTO_SSL3) +write_msg: +#endif + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +int ssl_parse_certificate( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(POLARSSL_SSL_SRV_C) + if( ssl->endpoint == SSL_IS_SERVER && + ( ssl->authmode == SSL_VERIFY_NONE || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) ) + { + ssl->session_negotiate->verify_result = BADCERT_SKIP_VERIFY; + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } +#endif + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + ssl->state++; + +#if defined(POLARSSL_SSL_SRV_C) +#if defined(POLARSSL_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->endpoint == SSL_IS_SERVER && + ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == SSL_MSG_ALERT && + ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT ) + { + SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + + ssl->session_negotiate->verify_result = BADCERT_MISSING; + if( ssl->authmode == SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->endpoint == SSL_IS_SERVER && + ssl->minor_ver != SSL_MINOR_VERSION_0 ) + { + if( ssl->in_hslen == 7 && + ssl->in_msgtype == SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 ) + { + SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + + ssl->session_negotiate->verify_result = BADCERT_MISSING; + if( ssl->authmode == SSL_VERIFY_REQUIRED ) + return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE ); + else + return( 0 ); + } + } +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ +#endif /* POLARSSL_SSL_SRV_C */ + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* + * Same message structure as in ssl_write_certificate() + */ + n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6]; + + if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + x509_crt_free( ssl->session_negotiate->peer_cert ); + polarssl_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = polarssl_malloc( + sizeof( x509_crt ) ) ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", + sizeof( x509_crt ) ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + x509_crt_init( ssl->session_negotiate->peer_cert ); + + i = 7; + + while( i < ssl->in_hslen ) + { + if( ssl->in_msg[i] != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_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 ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + ret = x509_crt_parse_der( ssl->session_negotiate->peer_cert, + ssl->in_msg + i, n ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, " x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + 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(POLARSSL_SSL_RENEGOTIATION) && defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT && + ssl->renegotiation == SSL_RENEGOTIATION ) + { + if( ssl->session->peer_cert == NULL ) + { + SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + return( POLARSSL_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 ) + { + SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + } +#endif /* POLARSSL_SSL_RENEGOTIATION && POLARSSL_SSL_CLI_C */ + + if( ssl->authmode != SSL_VERIFY_NONE ) + { + if( ssl->ca_chain == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED ); + } + + /* + * Main check: verify certificate + */ + ret = x509_crt_verify( ssl->session_negotiate->peer_cert, + ssl->ca_chain, ssl->ca_crl, ssl->peer_cn, + &ssl->session_negotiate->verify_result, + ssl->f_vrfy, ssl->p_vrfy ); + + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(POLARSSL_SSL_SET_CURVES) + { + pk_context *pk = &ssl->session_negotiate->peer_cert->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( pk_can_do( pk, POLARSSL_PK_ECKEY ) && + ! ssl_curve_is_acceptable( ssl, pk_ec( *pk )->grp.id ) ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* POLARSSL_SSL_SET_CURVES */ + + if( ssl_check_cert_usage( ssl->session_negotiate->peer_cert, + ciphersuite_info, + ! ssl->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE; + } + + if( ssl->authmode != SSL_VERIFY_REQUIRED ) + ret = 0; + } + + SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +int ssl_write_change_cipher_spec( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int ssl_parse_change_cipher_spec( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC ) + { + SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) + { + SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +void ssl_optimize_checksum( ssl_context *ssl, + const ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA512_C) + if( ciphersuite_info->mac == POLARSSL_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(POLARSSL_SHA256_C) + if( ciphersuite_info->mac != POLARSSL_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +static void ssl_update_checksum_start( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + md5_update( &ssl->handshake->fin_md5 , buf, len ); + sha1_update( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) + sha256_update( &ssl->handshake->fin_sha256, buf, len ); +#endif +#if defined(POLARSSL_SHA512_C) + sha512_update( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +} + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + md5_update( &ssl->handshake->fin_md5 , buf, len ); + sha1_update( &ssl->handshake->fin_sha1, buf, len ); +} +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +static void ssl_update_checksum_sha256( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + sha256_update( &ssl->handshake->fin_sha256, buf, len ); +} +#endif + +#if defined(POLARSSL_SHA512_C) +static void ssl_update_checksum_sha384( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + sha512_update( &ssl->handshake->fin_sha512, buf, len ); +} +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) +static void ssl_calc_finished_ssl( + ssl_context *ssl, unsigned char *buf, int from ) +{ + const char *sender; + md5_context md5; + sha1_context sha1; + + unsigned char padbuf[48]; + unsigned char md5sum[16]; + unsigned char sha1sum[20]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + /* + * SSLv3: + * hash = + * MD5( master + pad2 + + * MD5( handshake + sender + master + pad1 ) ) + * + SHA1( master + pad2 + + * SHA1( handshake + sender + master + pad1 ) ) + */ + +#if !defined(POLARSSL_MD5_ALT) + SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(POLARSSL_SHA1_ALT) + SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) ? "CLNT" + : "SRVR"; + + memset( padbuf, 0x36, 48 ); + + md5_update( &md5, (const unsigned char *) sender, 4 ); + md5_update( &md5, session->master, 48 ); + md5_update( &md5, padbuf, 48 ); + md5_finish( &md5, md5sum ); + + sha1_update( &sha1, (const unsigned char *) sender, 4 ); + sha1_update( &sha1, session->master, 48 ); + sha1_update( &sha1, padbuf, 40 ); + sha1_finish( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + md5_starts( &md5 ); + md5_update( &md5, session->master, 48 ); + md5_update( &md5, padbuf, 48 ); + md5_update( &md5, md5sum, 16 ); + md5_finish( &md5, buf ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, session->master, 48 ); + sha1_update( &sha1, padbuf , 40 ); + sha1_update( &sha1, sha1sum, 20 ); + sha1_finish( &sha1, buf + 16 ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + polarssl_zeroize( md5sum, sizeof( md5sum ) ); + polarssl_zeroize( sha1sum, sizeof( sha1sum ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_calc_finished_tls( + ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + md5_context md5; + sha1_context sha1; + unsigned char padbuf[36]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + /* + * TLSv1: + * hash = PRF( master, finished_label, + * MD5( handshake ) + SHA1( handshake ) )[0..11] + */ + +#if !defined(POLARSSL_MD5_ALT) + SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(POLARSSL_SHA1_ALT) + SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + md5_finish( &md5, padbuf ); + sha1_finish( &sha1, padbuf + 16 ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +static void ssl_calc_finished_tls_sha256( + ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + sha256_context sha256; + unsigned char padbuf[32]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + memcpy( &sha256, &ssl->handshake->fin_sha256, sizeof(sha256_context) ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(POLARSSL_SHA256_ALT) + SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + sha256_finish( &sha256, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + sha256_free( &sha256 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) +static void ssl_calc_finished_tls_sha384( + ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + sha512_context sha512; + unsigned char padbuf[48]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + memcpy( &sha512, &ssl->handshake->fin_sha512, sizeof(sha512_context) ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(POLARSSL_SHA512_ALT) + SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + sha512_finish( &sha512, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + sha512_free( &sha512 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +void ssl_handshake_wrapup( ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + + /* + * Free our handshake params + */ + ssl_handshake_free( ssl->handshake ); + polarssl_free( ssl->handshake ); + ssl->handshake = NULL; + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + ssl->renegotiation = SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Switch in our now active transform context + */ + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + polarssl_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + if( ssl->session ) + { +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + ssl_session_free( ssl->session ); + polarssl_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->f_set_cache != NULL && + ssl->session->length != 0 && + resume == 0 ) + { + if( ssl->f_set_cache( ssl->p_set_cache, ssl->session ) != 0 ) + SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int ssl_write_finished( ssl_context *ssl ) +{ + int ret, hash_len; + + SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + /* + * Set the out_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= 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->endpoint ); + + // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) + hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12; + +#if defined(POLARSSL_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 = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT ) + ssl->state = SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(POLARSSL_SSL_SRV_C) + if( ssl->endpoint == SSL_IS_SERVER ) + ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + memset( ssl->out_ctr, 0, 8 ); + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_activate != NULL ) + { + if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_activate", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +int ssl_parse_finished( ssl_context *ssl ) +{ + int ret; + unsigned int hash_len; + unsigned char buf[36]; + + SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->endpoint ^ 1 ); + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + memset( ssl->in_ctr, 0, 8 ); + + /* + * Set the in_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= 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(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_activate != NULL ) + { + if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_INBOUND ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_activate", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) + hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12; + + if( ssl->in_msg[0] != SSL_HS_FINISHED || + ssl->in_hslen != 4 + hash_len ) + { + SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_FINISHED ); + } + + if( safer_memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_FINISHED ); + } + +#if defined(POLARSSL_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT ) + ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(POLARSSL_SSL_SRV_C) + if( ssl->endpoint == SSL_IS_SERVER ) + ssl->state = SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + + return( 0 ); +} + +static void ssl_handshake_params_init( ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( ssl_handshake_params ) ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + md5_init( &handshake->fin_md5 ); + sha1_init( &handshake->fin_sha1 ); + md5_starts( &handshake->fin_md5 ); + sha1_starts( &handshake->fin_sha1 ); +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) + sha256_init( &handshake->fin_sha256 ); + sha256_starts( &handshake->fin_sha256, 0 ); +#endif +#if defined(POLARSSL_SHA512_C) + sha512_init( &handshake->fin_sha512 ); + sha512_starts( &handshake->fin_sha512, 1 ); +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + handshake->sig_alg = SSL_HASH_SHA1; + +#if defined(POLARSSL_DHM_C) + dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(POLARSSL_ECDH_C) + ecdh_init( &handshake->ecdh_ctx ); +#endif +} + +static void ssl_transform_init( ssl_transform *transform ) +{ + memset( transform, 0, sizeof(ssl_transform) ); + + cipher_init( &transform->cipher_ctx_enc ); + cipher_init( &transform->cipher_ctx_dec ); + + md_init( &transform->md_ctx_enc ); + md_init( &transform->md_ctx_dec ); +} + +void ssl_session_init( ssl_session *session ) +{ + memset( session, 0, sizeof(ssl_session) ); +} + +static int ssl_handshake_init( ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + 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 = polarssl_malloc( sizeof(ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = polarssl_malloc( sizeof(ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = polarssl_malloc( sizeof(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 ) + { + SSL_DEBUG_MSG( 1, ( "malloc() of ssl sub-contexts failed" ) ); + + polarssl_free( ssl->handshake ); + polarssl_free( ssl->transform_negotiate ); + polarssl_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + /* Initialize structures */ + ssl_session_init( ssl->session_negotiate ); + ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + ssl->handshake->key_cert = ssl->key_cert; +#endif + + return( 0 ); +} + +/* + * Initialize an SSL context + */ +int ssl_init( ssl_context *ssl ) +{ + int ret; + int len = SSL_BUFFER_LEN; + + memset( ssl, 0, sizeof( ssl_context ) ); + + /* + * Sane defaults + */ + ssl->min_major_ver = SSL_MIN_MAJOR_VERSION; + ssl->min_minor_ver = SSL_MIN_MINOR_VERSION; + ssl->max_major_ver = SSL_MAX_MAJOR_VERSION; + ssl->max_minor_ver = SSL_MAX_MINOR_VERSION; + + ssl_set_ciphersuites( ssl, ssl_list_ciphersuites() ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) + ssl->renego_max_records = SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( ssl->renego_period, 0xFF, 7 ); + ssl->renego_period[7] = 0x00; +#endif + +#if defined(POLARSSL_DHM_C) + if( ( ret = mpi_read_string( &ssl->dhm_P, 16, + POLARSSL_DHM_RFC5114_MODP_1024_P) ) != 0 || + ( ret = mpi_read_string( &ssl->dhm_G, 16, + POLARSSL_DHM_RFC5114_MODP_1024_G) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_read_string", ret ); + return( ret ); + } +#endif + + /* + * Prepare base structures + */ + if( ( ssl->in_ctr = polarssl_malloc( len ) ) == NULL || + ( ssl->out_ctr = polarssl_malloc( len ) ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) ); + polarssl_free( ssl->in_ctr ); + ssl->in_ctr = NULL; + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN ); + memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); + + ssl->in_hdr = ssl->in_ctr + 8; + ssl->in_iv = ssl->in_ctr + 13; + ssl->in_msg = ssl->in_ctr + 13; + + ssl->out_hdr = ssl->out_ctr + 8; + ssl->out_iv = ssl->out_ctr + 13; + ssl->out_msg = ssl->out_ctr + 13; + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + ssl->encrypt_then_mac = SSL_ETM_ENABLED; +#endif + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + ssl->extended_ms = SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl->ticket_lifetime = SSL_DEFAULT_TICKET_LIFETIME; +#endif + +#if defined(POLARSSL_SSL_SET_CURVES) + ssl->curve_list = ecp_grp_id_list( ); +#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 ssl_session_reset( ssl_context *ssl ) +{ + int ret; + + ssl->state = SSL_HELLO_REQUEST; + +#if defined(POLARSSL_SSL_RENEGOTIATION) + ssl->renegotiation = SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION; + + ssl->in_offt = NULL; + + ssl->in_msg = ssl->in_ctr + 13; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + ssl->in_left = 0; + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + ssl->record_read = 0; + + ssl->out_msg = ssl->out_ctr + 13; + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) + if( ssl->split_done != SSL_CBC_RECORD_SPLITTING_DISABLED ) + ssl->split_done = 0; +#endif + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); + memset( ssl->in_ctr, 0, SSL_BUFFER_LEN ); + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_reset != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_reset()" ) ); + if( ( ret = ssl_hw_record_reset( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_reset", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + polarssl_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + ssl_session_free( ssl->session ); + polarssl_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(POLARSSL_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static void ssl_ticket_keys_free( ssl_ticket_keys *tkeys ) +{ + aes_free( &tkeys->enc ); + aes_free( &tkeys->dec ); + + polarssl_zeroize( tkeys, sizeof(ssl_ticket_keys) ); +} + +/* + * Allocate and initialize ticket keys + */ +static int ssl_ticket_keys_init( ssl_context *ssl ) +{ + int ret; + ssl_ticket_keys *tkeys; + unsigned char buf[16]; + + if( ssl->ticket_keys != NULL ) + return( 0 ); + + tkeys = polarssl_malloc( sizeof(ssl_ticket_keys) ); + if( tkeys == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + aes_init( &tkeys->enc ); + aes_init( &tkeys->dec ); + + if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->key_name, 16 ) ) != 0 ) + { + ssl_ticket_keys_free( tkeys ); + polarssl_free( tkeys ); + return( ret ); + } + + if( ( ret = ssl->f_rng( ssl->p_rng, buf, 16 ) ) != 0 || + ( ret = aes_setkey_enc( &tkeys->enc, buf, 128 ) ) != 0 || + ( ret = aes_setkey_dec( &tkeys->dec, buf, 128 ) ) != 0 ) + { + ssl_ticket_keys_free( tkeys ); + polarssl_free( tkeys ); + return( ret ); + } + + if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->mac_key, 16 ) ) != 0 ) + { + ssl_ticket_keys_free( tkeys ); + polarssl_free( tkeys ); + return( ret ); + } + + ssl->ticket_keys = tkeys; + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL set accessors + */ +void ssl_set_endpoint( ssl_context *ssl, int endpoint ) +{ + ssl->endpoint = endpoint; + +#if defined(POLARSSL_SSL_SESSION_TICKETS) && \ + defined(POLARSSL_SSL_CLI_C) + if( endpoint == SSL_IS_CLIENT ) + ssl->session_tickets = SSL_SESSION_TICKETS_ENABLED; +#endif + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + if( endpoint == SSL_IS_SERVER ) + ssl->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; +#endif +} + +void ssl_set_authmode( ssl_context *ssl, int authmode ) +{ + ssl->authmode = authmode; +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +void ssl_set_verify( ssl_context *ssl, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + ssl->f_vrfy = f_vrfy; + ssl->p_vrfy = p_vrfy; +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +void ssl_set_rng( ssl_context *ssl, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ssl->f_rng = f_rng; + ssl->p_rng = p_rng; +} + +void ssl_set_dbg( ssl_context *ssl, + void (*f_dbg)(void *, int, const char *), + void *p_dbg ) +{ + ssl->f_dbg = f_dbg; + ssl->p_dbg = p_dbg; +} + +void ssl_set_bio( ssl_context *ssl, + int (*f_recv)(void *, unsigned char *, size_t), void *p_recv, + int (*f_send)(void *, const unsigned char *, size_t), void *p_send ) +{ + ssl->f_recv = f_recv; + ssl->f_send = f_send; + ssl->p_recv = p_recv; + ssl->p_send = p_send; +} + +#if defined(POLARSSL_SSL_SRV_C) +void ssl_set_session_cache( ssl_context *ssl, + int (*f_get_cache)(void *, ssl_session *), void *p_get_cache, + int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache ) +{ + ssl->f_get_cache = f_get_cache; + ssl->p_get_cache = p_get_cache; + ssl->f_set_cache = f_set_cache; + ssl->p_set_cache = p_set_cache; +} +#endif /* POLARSSL_SSL_SRV_C */ + +#if defined(POLARSSL_SSL_CLI_C) +int ssl_set_session( ssl_context *ssl, const ssl_session *session ) +{ + int ret; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->endpoint != SSL_IS_CLIENT ) + { + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* POLARSSL_SSL_CLI_C */ + +void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ) +{ + ssl->ciphersuite_list[SSL_MINOR_VERSION_0] = ciphersuites; + ssl->ciphersuite_list[SSL_MINOR_VERSION_1] = ciphersuites; + ssl->ciphersuite_list[SSL_MINOR_VERSION_2] = ciphersuites; + ssl->ciphersuite_list[SSL_MINOR_VERSION_3] = ciphersuites; +} + +void ssl_set_ciphersuites_for_version( ssl_context *ssl, + const int *ciphersuites, + int major, int minor ) +{ + if( major != SSL_MAJOR_VERSION_3 ) + return; + + if( minor < SSL_MINOR_VERSION_0 || minor > SSL_MINOR_VERSION_3 ) + return; + + ssl->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/* Add a new (empty) key_cert entry an return a pointer to it */ +static ssl_key_cert *ssl_add_key_cert( ssl_context *ssl ) +{ + ssl_key_cert *key_cert, *last; + + key_cert = polarssl_malloc( sizeof(ssl_key_cert) ); + if( key_cert == NULL ) + return( NULL ); + + memset( key_cert, 0, sizeof( ssl_key_cert ) ); + + /* Append the new key_cert to the (possibly empty) current list */ + if( ssl->key_cert == NULL ) + { + ssl->key_cert = key_cert; + if( ssl->handshake != NULL ) + ssl->handshake->key_cert = key_cert; + } + else + { + last = ssl->key_cert; + while( last->next != NULL ) + last = last->next; + last->next = key_cert; + } + + return( key_cert ); +} + +void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain, + x509_crl *ca_crl, const char *peer_cn ) +{ + ssl->ca_chain = ca_chain; + ssl->ca_crl = ca_crl; + ssl->peer_cn = peer_cn; +} + +int ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert, + pk_context *pk_key ) +{ + ssl_key_cert *key_cert = ssl_add_key_cert( ssl ); + + if( key_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + key_cert->cert = own_cert; + key_cert->key = pk_key; + + return( 0 ); +} + +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +#if defined(POLARSSL_RSA_C) +int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert, + rsa_context *rsa_key ) +{ + int ret; + ssl_key_cert *key_cert = ssl_add_key_cert( ssl ); + + if( key_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + key_cert->key = polarssl_malloc( sizeof(pk_context) ); + if( key_cert->key == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + pk_init( key_cert->key ); + + ret = pk_init_ctx( key_cert->key, pk_info_from_type( POLARSSL_PK_RSA ) ); + if( ret != 0 ) + return( ret ); + + if( ( ret = rsa_copy( pk_rsa( *key_cert->key ), rsa_key ) ) != 0 ) + return( ret ); + + key_cert->cert = own_cert; + key_cert->key_own_alloc = 1; + + return( 0 ); +} +#endif /* POLARSSL_RSA_C */ + +int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert, + void *rsa_key, + rsa_decrypt_func rsa_decrypt, + rsa_sign_func rsa_sign, + rsa_key_len_func rsa_key_len ) +{ + int ret; + ssl_key_cert *key_cert = ssl_add_key_cert( ssl ); + + if( key_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + key_cert->key = polarssl_malloc( sizeof(pk_context) ); + if( key_cert->key == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + pk_init( key_cert->key ); + + if( ( ret = pk_init_ctx_rsa_alt( key_cert->key, rsa_key, + rsa_decrypt, rsa_sign, rsa_key_len ) ) != 0 ) + return( ret ); + + key_cert->cert = own_cert; + key_cert->key_own_alloc = 1; + + return( 0 ); +} +#endif /* POLARSSL_DEPRECATED_REMOVED */ +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_set_psk( ssl_context *ssl, 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( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > POLARSSL_PSK_MAX_LEN ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->psk != NULL || ssl->psk_identity != NULL ) + { + polarssl_free( ssl->psk ); + polarssl_free( ssl->psk_identity ); + } + + if( ( ssl->psk = polarssl_malloc( psk_len ) ) == NULL || + ( ssl->psk_identity = polarssl_malloc( psk_identity_len ) ) == NULL ) + { + polarssl_free( ssl->psk ); + ssl->psk = NULL; + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + ssl->psk_len = psk_len; + ssl->psk_identity_len = psk_identity_len; + + memcpy( ssl->psk, psk, ssl->psk_len ); + memcpy( ssl->psk_identity, psk_identity, ssl->psk_identity_len ); + + return( 0 ); +} + +void ssl_set_psk_cb( ssl_context *ssl, + int (*f_psk)(void *, ssl_context *, const unsigned char *, + size_t), + void *p_psk ) +{ + ssl->f_psk = f_psk; + ssl->p_psk = p_psk; +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_DHM_C) +int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ) +{ + int ret; + + if( ( ret = mpi_read_string( &ssl->dhm_P, 16, dhm_P ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_read_string", ret ); + return( ret ); + } + + if( ( ret = mpi_read_string( &ssl->dhm_G, 16, dhm_G ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_read_string", ret ); + return( ret ); + } + + return( 0 ); +} + +int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ) +{ + int ret; + + if( ( ret = mpi_copy( &ssl->dhm_P, &dhm_ctx->P ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_copy", ret ); + return( ret ); + } + + if( ( ret = mpi_copy( &ssl->dhm_G, &dhm_ctx->G ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_copy", ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_SSL_SET_CURVES) +/* + * Set the allowed elliptic curves + */ +void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curve_list ) +{ + ssl->curve_list = curve_list; +} +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +int ssl_set_hostname( ssl_context *ssl, const char *hostname ) +{ + if( hostname == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + ssl->hostname_len = strlen( hostname ); + + if( ssl->hostname_len + 1 == 0 ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + ssl->hostname = polarssl_malloc( ssl->hostname_len + 1 ); + + if( ssl->hostname == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + memcpy( ssl->hostname, (const unsigned char *) hostname, + ssl->hostname_len ); + + ssl->hostname[ssl->hostname_len] = '\0'; + + return( 0 ); +} + +void ssl_set_sni( ssl_context *ssl, + int (*f_sni)(void *, ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + ssl->f_sni = f_sni; + ssl->p_sni = p_sni; +} +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +#if defined(POLARSSL_SSL_ALPN) +int ssl_set_alpn_protocols( ssl_context *ssl, 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( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl->alpn_list = protos; + + return( 0 ); +} + +const char *ssl_get_alpn_protocol( const ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* POLARSSL_SSL_ALPN */ + +void ssl_set_max_version( ssl_context *ssl, int major, int minor ) +{ + if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION && + minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION ) + { + ssl->max_major_ver = major; + ssl->max_minor_ver = minor; + } +} + +void ssl_set_min_version( ssl_context *ssl, int major, int minor ) +{ + if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION && + minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION ) + { + ssl->min_major_ver = major; + ssl->min_minor_ver = minor; + } +} + +#if defined(POLARSSL_SSL_FALLBACK_SCSV) && defined(POLARSSL_SSL_CLI_C) +void ssl_set_fallback( ssl_context *ssl, char fallback ) +{ + ssl->fallback = fallback; +} +#endif + +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) +void ssl_set_encrypt_then_mac( ssl_context *ssl, char etm ) +{ + ssl->encrypt_then_mac = etm; +} +#endif + +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +void ssl_set_extended_master_secret( ssl_context *ssl, char ems ) +{ + ssl->extended_ms = ems; +} +#endif + +void ssl_set_arc4_support( ssl_context *ssl, char arc4 ) +{ + ssl->arc4_disabled = arc4; +} + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ) +{ + if( mfl_code >= SSL_MAX_FRAG_LEN_INVALID || + mfl_code_to_length[mfl_code] > SSL_MAX_CONTENT_LEN ) + { + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +int ssl_set_truncated_hmac( ssl_context *ssl, int truncate ) +{ + ssl->trunc_hmac = truncate; + + return( 0 ); +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) +void ssl_set_cbc_record_splitting( ssl_context *ssl, char split ) +{ + ssl->split_done = split; +} +#endif + +void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy ) +{ + ssl->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(POLARSSL_SSL_RENEGOTIATION) +void ssl_set_renegotiation( ssl_context *ssl, int renegotiation ) +{ + ssl->disable_renegotiation = renegotiation; +} + +void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records ) +{ + ssl->renego_max_records = max_records; +} + +void ssl_set_renegotiation_period( ssl_context *ssl, + const unsigned char period[8] ) +{ + memcpy( ssl->renego_period, period, 8 ); +} +#endif /* POLARSSL_SSL_RENEGOTIATION */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +int ssl_set_session_tickets( ssl_context *ssl, int use_tickets ) +{ + ssl->session_tickets = use_tickets; + +#if defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT ) + return( 0 ); +#endif + + if( use_tickets == SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + if( ssl->f_rng == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + return( ssl_ticket_keys_init( ssl ) ); +} + +void ssl_set_session_ticket_lifetime( ssl_context *ssl, int lifetime ) +{ + ssl->ticket_lifetime = lifetime; +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL get accessors + */ +size_t ssl_get_bytes_avail( const ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +int ssl_get_verify_result( const ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( -1 ); +} + +const char *ssl_get_ciphersuite( const ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *ssl_get_version( const ssl_context *ssl ) +{ + switch( ssl->minor_ver ) + { + case SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + break; + } + return( "unknown" ); +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +const x509_crt *ssl_get_peer_cert( const ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return( ssl->session->peer_cert ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_SSL_CLI_C) +int ssl_get_session( const ssl_context *ssl, ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->endpoint != SSL_IS_CLIENT ) + { + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ssl_session_copy( dst, ssl->session ) ); +} +#endif /* POLARSSL_SSL_CLI_C */ + +/* + * Perform a single step of the SSL handshake + */ +int ssl_handshake_step( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + +#if defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT ) + ret = ssl_handshake_client_step( ssl ); +#endif +#if defined(POLARSSL_SSL_SRV_C) + if( ssl->endpoint == SSL_IS_SERVER ) + ret = ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int ssl_handshake( ssl_context *ssl ) +{ + int ret = 0; + + SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + while( ssl->state != SSL_HANDSHAKE_OVER ) + { + ret = ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(POLARSSL_SSL_RENEGOTIATION) +#if defined(POLARSSL_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_HELLO_REQUEST; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling ssl_renegotiate(), + * - client: receiving a HelloRequest during ssl_read(), + * - server: receiving any handshake message on server during 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 ssl_renegotiate() or ssl_read() respectively. + */ +static int ssl_start_renegotiation( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + ssl->state = SSL_HELLO_REQUEST; + ssl->renegotiation = SSL_RENEGOTIATION; + + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int ssl_renegotiate( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + +#if defined(POLARSSL_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->endpoint == SSL_IS_SERVER ) + { + if( ssl->state != SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renegotiation = SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* POLARSSL_SSL_SRV_C */ + +#if defined(POLARSSL_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renegotiation != SSL_RENEGOTIATION ) + { + if( ssl->state != SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + } +#endif /* POLARSSL_SSL_CLI_C */ + + return( ret ); +} + +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( ssl_context *ssl ) +{ + if( ssl->state != SSL_HANDSHAKE_OVER || + ssl->renegotiation == SSL_RENEGOTIATION_PENDING || + ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + // TODO: adapt for DTLS + if( memcmp( ssl->in_ctr, ssl->renego_period, 8 ) <= 0 && + memcmp( ssl->out_ctr, ssl->renego_period, 8 ) <= 0 ) + { + return( 0 ); + } + + SSL_DEBUG_MSG( 0, ( "record counter limit reached: renegotiate" ) ); + return( ssl_renegotiate( ssl ) ); +} +#endif /* POLARSSL_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret, record_read = 0; + size_t n; + + SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != SSL_HANDSHAKE_OVER ) + { + ret = ssl_handshake( ssl ); + if( ret == POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) + { + record_read = 1; + } + else if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + } + + if( ssl->in_offt == NULL ) + { + if( ! record_read ) + { + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + if( ret == POLARSSL_ERR_SSL_CONN_EOF ) + return( 0 ); + + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + if( ret == POLARSSL_ERR_SSL_CONN_EOF ) + return( 0 ); + + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + } + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ssl->in_msgtype == SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + +#if defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT && + ( ssl->in_msg[0] != SSL_HS_HELLO_REQUEST || + ssl->in_hslen != 4 ) ) + { + SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif + + if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == + SSL_LEGACY_NO_RENEGOTIATION ) ) + { + SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + /* + * SSLv3 does not have a "no_renegotiation" alert + */ + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 ) + { + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_WARNING, + SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else + { + ret = ssl_start_renegotiation( ssl ); + if( ret == POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) + { + record_read = 1; + } + else if( ret != 0 ) + { + 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 ssl_read() again */ + if( ! record_read ) + return( POLARSSL_ERR_NET_WANT_READ ); + } + else if( ssl->renegotiation == SSL_RENEGOTIATION_PENDING ) + { + ssl->renego_records_seen++; + + if( ssl->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->renego_max_records ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } +#endif /* POLARSSL_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by ssl_read_record() */ + if( ssl->in_msgtype == SSL_MSG_ALERT ) + { + SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( POLARSSL_ERR_NET_WANT_READ ); + } + + if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) + { + SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + } + + 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; + + 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( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; + size_t n; + unsigned int max_len = SSL_MAX_CONTENT_LEN; + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = mfl_code_to_length[ssl->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]; + } +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + + n = ( len < max_len) ? len : max_len; + + if( ssl->out_left != 0 ) + { + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); + return( ret ); + } + } + else + { + ssl->out_msglen = n; + ssl->out_msgtype = SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, n ); + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) n ); +} + +/* + * 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(POLARSSL_SSL_CBC_RECORD_SPLITTING) +static int ssl_write_split( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; + + if( ssl->split_done == SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > SSL_MINOR_VERSION_1 || + cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != POLARSSL_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 /* POLARSSL_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write" ) ); + +#if defined(POLARSSL_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != SSL_HANDSHAKE_OVER ) + { + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int ssl_close_notify( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( ssl_flush_output( ssl ) ); + + if( ssl->state == SSL_HANDSHAKE_OVER ) + { + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_WARNING, + SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_send_alert_message", ret ); + return( ret ); + } + } + + SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void ssl_transform_free( ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(POLARSSL_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + cipher_free( &transform->cipher_ctx_enc ); + cipher_free( &transform->cipher_ctx_dec ); + + md_free( &transform->md_ctx_enc ); + md_free( &transform->md_ctx_dec ); + + polarssl_zeroize( transform, sizeof( ssl_transform ) ); +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +static void ssl_key_cert_free( ssl_key_cert *key_cert ) +{ + ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + + if( cur->key_own_alloc ) + { + pk_free( cur->key ); + polarssl_free( cur->key ); + } + polarssl_free( cur ); + + cur = next; + } +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +void ssl_handshake_free( ssl_handshake_params *handshake ) +{ + if( handshake == NULL ) + return; + +#if defined(POLARSSL_DHM_C) + dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(POLARSSL_ECDH_C) + ecdh_free( &handshake->ecdh_ctx ); +#endif + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + /* explicit void pointer cast for buggy MS compiler */ + polarssl_free( (void *) handshake->curves ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) && \ + defined(POLARSSL_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 ) + { + ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + polarssl_free( cur ); + cur = next; + } + } +#endif /* POLARSSL_X509_CRT_PARSE_C && POLARSSL_SSL_SERVER_NAME_INDICATION */ + + polarssl_zeroize( handshake, sizeof( ssl_handshake_params ) ); +} + +void ssl_session_free( ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(POLARSSL_X509_CRT_PARSE_C) + if( session->peer_cert != NULL ) + { + x509_crt_free( session->peer_cert ); + polarssl_free( session->peer_cert ); + } +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + polarssl_free( session->ticket ); +#endif + + polarssl_zeroize( session, sizeof( ssl_session ) ); +} + +/* + * Free an SSL context + */ +void ssl_free( ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_ctr != NULL ) + { + polarssl_zeroize( ssl->out_ctr, SSL_BUFFER_LEN ); + polarssl_free( ssl->out_ctr ); + } + + if( ssl->in_ctr != NULL ) + { + polarssl_zeroize( ssl->in_ctr, SSL_BUFFER_LEN ); + polarssl_free( ssl->in_ctr ); + } + +#if defined(POLARSSL_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + polarssl_zeroize( ssl->compress_buf, SSL_BUFFER_LEN ); + polarssl_free( ssl->compress_buf ); + } +#endif + +#if defined(POLARSSL_DHM_C) + mpi_free( &ssl->dhm_P ); + mpi_free( &ssl->dhm_G ); +#endif + + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + polarssl_free( ssl->transform ); + } + + if( ssl->handshake ) + { + ssl_handshake_free( ssl->handshake ); + ssl_transform_free( ssl->transform_negotiate ); + ssl_session_free( ssl->session_negotiate ); + + polarssl_free( ssl->handshake ); + polarssl_free( ssl->transform_negotiate ); + polarssl_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + ssl_session_free( ssl->session ); + polarssl_free( ssl->session ); + } + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->ticket_keys ) + { + ssl_ticket_keys_free( ssl->ticket_keys ); + polarssl_free( ssl->ticket_keys ); + } +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + if( ssl->hostname != NULL ) + { + polarssl_zeroize( ssl->hostname, ssl->hostname_len ); + polarssl_free( ssl->hostname ); + ssl->hostname_len = 0; + } +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ssl->psk != NULL ) + { + polarssl_zeroize( ssl->psk, ssl->psk_len ); + polarssl_zeroize( ssl->psk_identity, ssl->psk_identity_len ); + polarssl_free( ssl->psk ); + polarssl_free( ssl->psk_identity ); + ssl->psk_len = 0; + ssl->psk_identity_len = 0; + } +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + ssl_key_cert_free( ssl->key_cert ); +#endif + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_finish != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_finish()" ) ); + ssl_hw_record_finish( ssl ); + } +#endif + + SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + polarssl_zeroize( ssl, sizeof( ssl_context ) ); +} + +#if defined(POLARSSL_PK_C) +/* + * Convert between POLARSSL_PK_XXX and SSL_SIG_XXX + */ +unsigned char ssl_sig_from_pk( pk_context *pk ) +{ +#if defined(POLARSSL_RSA_C) + if( pk_can_do( pk, POLARSSL_PK_RSA ) ) + return( SSL_SIG_RSA ); +#endif +#if defined(POLARSSL_ECDSA_C) + if( pk_can_do( pk, POLARSSL_PK_ECDSA ) ) + return( SSL_SIG_ECDSA ); +#endif + return( SSL_SIG_ANON ); +} + +pk_type_t ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(POLARSSL_RSA_C) + case SSL_SIG_RSA: + return( POLARSSL_PK_RSA ); +#endif +#if defined(POLARSSL_ECDSA_C) + case SSL_SIG_ECDSA: + return( POLARSSL_PK_ECDSA ); +#endif + default: + return( POLARSSL_PK_NONE ); + } +} +#endif /* POLARSSL_PK_C */ + +/* + * Convert between SSL_HASH_XXX and POLARSSL_MD_XXX + */ +md_type_t ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(POLARSSL_MD5_C) + case SSL_HASH_MD5: + return( POLARSSL_MD_MD5 ); +#endif +#if defined(POLARSSL_SHA1_C) + case SSL_HASH_SHA1: + return( POLARSSL_MD_SHA1 ); +#endif +#if defined(POLARSSL_SHA256_C) + case SSL_HASH_SHA224: + return( POLARSSL_MD_SHA224 ); + case SSL_HASH_SHA256: + return( POLARSSL_MD_SHA256 ); +#endif +#if defined(POLARSSL_SHA512_C) + case SSL_HASH_SHA384: + return( POLARSSL_MD_SHA384 ); + case SSL_HASH_SHA512: + return( POLARSSL_MD_SHA512 ); +#endif + default: + return( POLARSSL_MD_NONE ); + } +} + +#if defined(POLARSSL_SSL_SET_CURVES) +/* + * Check is a curve proposed by the peer is in our list. + * Return 1 if we're willing to use it, 0 otherwise. + */ +int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id ) +{ + const ecp_group_id *gid; + + for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 1 ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SET_CURVES */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +int ssl_check_cert_usage( const x509_crt *cert, + const ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + int *flags ) +{ + int ret = 0; +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(POLARSSL_X509_CHECK_KEY_USAGE) && \ + !defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); + ((void) flags); +#endif + +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + if( cert_endpoint == SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_RSA: + case POLARSSL_KEY_EXCHANGE_RSA_PSK: + usage = KU_KEY_ENCIPHERMENT; + break; + + case POLARSSL_KEY_EXCHANGE_DHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA: + usage = KU_DIGITAL_SIGNATURE; + break; + + case POLARSSL_KEY_EXCHANGE_ECDH_RSA: + case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA: + usage = KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case POLARSSL_KEY_EXCHANGE_NONE: + case POLARSSL_KEY_EXCHANGE_PSK: + case POLARSSL_KEY_EXCHANGE_DHE_PSK: + case POLARSSL_KEY_EXCHANGE_ECDHE_PSK: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and ecdsa_sign for now */ + usage = KU_DIGITAL_SIGNATURE; + } + + if( x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= BADCERT_KEY_USAGE; + ret = -1; + } +#else + ((void) ciphersuite); +#endif /* POLARSSL_X509_CHECK_KEY_USAGE */ + +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == SSL_IS_SERVER ) + { + ext_oid = OID_SERVER_AUTH; + ext_len = OID_SIZE( OID_SERVER_AUTH ); + } + else + { + ext_oid = OID_CLIENT_AUTH; + ext_len = OID_SIZE( OID_CLIENT_AUTH ); + } + + if( x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= BADCERT_EXT_KEY_USAGE; + ret = -1; + } +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( ret ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#endif /* POLARSSL_SSL_TLS_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/threading.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/threading.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,111 @@ +/* + * Threading abstraction layer + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_THREADING_C) + +#include "polarssl/threading.h" + +#if defined(POLARSSL_THREADING_PTHREAD) +static int threading_mutex_init_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_init( mutex, NULL ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_free_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_destroy( mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_lock_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_init_pthread; +int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_free_pthread; +int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_unlock_pthread; +#endif /* POLARSSL_THREADING_PTHREAD */ + +#if defined(POLARSSL_THREADING_ALT) +static int threading_mutex_fail( threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); +} + +int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_fail; +int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_fail; +int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_fail; +int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_fail; + +int threading_set_alt( int (*mutex_init)( threading_mutex_t * ), + int (*mutex_free)( threading_mutex_t * ), + int (*mutex_lock)( threading_mutex_t * ), + int (*mutex_unlock)( threading_mutex_t * ) ) +{ + polarssl_mutex_init = mutex_init; + polarssl_mutex_free = mutex_free; + polarssl_mutex_lock = mutex_lock; + polarssl_mutex_unlock = mutex_unlock; + + return( 0 ); +} +#endif /* POLARSSL_THREADING_ALT_C */ + +#endif /* POLARSSL_THREADING_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/timing.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/timing.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,505 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif + +#if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT) + +#include "polarssl/timing.h" + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include <windows.h> +#include <winbase.h> + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include <unistd.h> +#include <sys/types.h> +#include <sys/time.h> +#include <signal.h> +#include <time.h> + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long 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 /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) + +#define POLARSSL_HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long 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 /* !POLARSSL_HAVE_HARDCLOCK */ + +volatile int alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long get_timer( struct 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 ); + alarmed = 1; + return( TRUE ); +} + +void set_alarm( int seconds ) +{ + DWORD ThreadId; + + alarmed = 0; + alarmMs = seconds * 1000; + CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); +} + +void m_sleep( int milliseconds ) +{ + Sleep( milliseconds ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long get_timer( struct 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 ); +} + +#if defined(INTEGRITY) +void m_sleep( int milliseconds ) +{ + usleep( milliseconds * 1000 ); +} + +#else /* INTEGRITY */ + +static void sighandler( int signum ) +{ + alarmed = 1; + signal( signum, sighandler ); +} + +void set_alarm( int seconds ) +{ + alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); +} + +void m_sleep( int milliseconds ) +{ + struct timeval tv; + + tv.tv_sec = milliseconds / 1000; + tv.tv_usec = ( milliseconds % 1000 ) * 1000; + + select( 0, NULL, NULL, NULL, &tv ); +} +#endif /* INTEGRITY */ + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if defined(POLARSSL_SELF_TEST) + +/* To test net_usleep against our functions */ +#if defined(POLARSSL_NET_C) && defined(POLARSSL_HAVE_TIME) +#include "polarssl/net.h" +#endif + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) get_timer( &hires, 1 ); + + while( get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int timing_self_test( int verbose ) +{ + unsigned long cycles, ratio; + unsigned long millisecs, secs; + int hardfail; + struct hr_time hires; + + if( verbose != 0 ) + polarssl_printf( " TIMING tests note: will take some time!\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #1 (m_sleep / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + m_sleep( (int)( 500 * secs ) ); + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 450 * secs || millisecs > 550 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #2 (set_alarm / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + set_alarm( (int) secs ); + while( !alarmed ) + ; + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 900 * secs || millisecs > 1100 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_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 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = hardclock(); + busy_msleep( millisecs ); + cycles = hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = hardclock(); + busy_msleep( millisecs ); + cycles = 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 ) + polarssl_printf( "passed\n" ); + +#if defined(POLARSSL_NET_C) && defined(POLARSSL_HAVE_TIME) + if( verbose != 0 ) + polarssl_printf( " TIMING test #4 (net_usleep/ get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + net_usleep( 500000 * secs ); + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 450 * secs || millisecs > 550 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); +#endif /* POLARSSL_NET_C */ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */ +
diff -r 000000000000 -r 137634ff4186 polarssl/version.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/version.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,52 @@ +/* + * Version information + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_VERSION_C) + +#include "polarssl/version.h" +#include <string.h> + +unsigned int version_get_number() +{ + return( POLARSSL_VERSION_NUMBER ); +} + +void version_get_string( char *string ) +{ + memcpy( string, POLARSSL_VERSION_STRING, + sizeof( POLARSSL_VERSION_STRING ) ); +} + +void version_get_string_full( char *string ) +{ + memcpy( string, POLARSSL_VERSION_STRING_FULL, + sizeof( POLARSSL_VERSION_STRING_FULL ) ); +} + +#endif /* POLARSSL_VERSION_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/version_features.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/version_features.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,591 @@ +/* + * Version feature information + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_VERSION_C) + +#include "polarssl/version.h" + +#include <string.h> + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +static const char *features[] = { +#if defined(POLARSSL_VERSION_FEATURES) +#if defined(POLARSSL_HAVE_INT8) + "POLARSSL_HAVE_INT8", +#endif /* POLARSSL_HAVE_INT8 */ +#if defined(POLARSSL_HAVE_INT16) + "POLARSSL_HAVE_INT16", +#endif /* POLARSSL_HAVE_INT16 */ +#if defined(POLARSSL_HAVE_LONGLONG) + "POLARSSL_HAVE_LONGLONG", +#endif /* POLARSSL_HAVE_LONGLONG */ +#if defined(POLARSSL_HAVE_ASM) + "POLARSSL_HAVE_ASM", +#endif /* POLARSSL_HAVE_ASM */ +#if defined(POLARSSL_HAVE_SSE2) + "POLARSSL_HAVE_SSE2", +#endif /* POLARSSL_HAVE_SSE2 */ +#if defined(POLARSSL_HAVE_TIME) + "POLARSSL_HAVE_TIME", +#endif /* POLARSSL_HAVE_TIME */ +#if defined(POLARSSL_HAVE_IPV6) + "POLARSSL_HAVE_IPV6", +#endif /* POLARSSL_HAVE_IPV6 */ +#if defined(POLARSSL_PLATFORM_MEMORY) + "POLARSSL_PLATFORM_MEMORY", +#endif /* POLARSSL_PLATFORM_MEMORY */ +#if defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS) + "POLARSSL_PLATFORM_NO_STD_FUNCTIONS", +#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(POLARSSL_PLATFORM_EXIT_ALT) + "POLARSSL_PLATFORM_EXIT_ALT", +#endif /* POLARSSL_PLATFORM_EXIT_ALT */ +#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) + "POLARSSL_PLATFORM_FPRINTF_ALT", +#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */ +#if defined(POLARSSL_PLATFORM_PRINTF_ALT) + "POLARSSL_PLATFORM_PRINTF_ALT", +#endif /* POLARSSL_PLATFORM_PRINTF_ALT */ +#if defined(POLARSSL_PLATFORM_SNPRINTF_ALT) + "POLARSSL_PLATFORM_SNPRINTF_ALT", +#endif /* POLARSSL_PLATFORM_SNPRINTF_ALT */ +#if defined(POLARSSL_DEPRECATED_WARNING) + "POLARSSL_DEPRECATED_WARNING", +#endif /* POLARSSL_DEPRECATED_WARNING */ +#if defined(POLARSSL_DEPRECATED_REMOVED) + "POLARSSL_DEPRECATED_REMOVED", +#endif /* POLARSSL_DEPRECATED_REMOVED */ +#if defined(POLARSSL_TIMING_ALT) + "POLARSSL_TIMING_ALT", +#endif /* POLARSSL_TIMING_ALT */ +#if defined(POLARSSL_AES_ALT) + "POLARSSL_AES_ALT", +#endif /* POLARSSL_AES_ALT */ +#if defined(POLARSSL_ARC4_ALT) + "POLARSSL_ARC4_ALT", +#endif /* POLARSSL_ARC4_ALT */ +#if defined(POLARSSL_BLOWFISH_ALT) + "POLARSSL_BLOWFISH_ALT", +#endif /* POLARSSL_BLOWFISH_ALT */ +#if defined(POLARSSL_CAMELLIA_ALT) + "POLARSSL_CAMELLIA_ALT", +#endif /* POLARSSL_CAMELLIA_ALT */ +#if defined(POLARSSL_DES_ALT) + "POLARSSL_DES_ALT", +#endif /* POLARSSL_DES_ALT */ +#if defined(POLARSSL_XTEA_ALT) + "POLARSSL_XTEA_ALT", +#endif /* POLARSSL_XTEA_ALT */ +#if defined(POLARSSL_MD2_ALT) + "POLARSSL_MD2_ALT", +#endif /* POLARSSL_MD2_ALT */ +#if defined(POLARSSL_MD4_ALT) + "POLARSSL_MD4_ALT", +#endif /* POLARSSL_MD4_ALT */ +#if defined(POLARSSL_MD5_ALT) + "POLARSSL_MD5_ALT", +#endif /* POLARSSL_MD5_ALT */ +#if defined(POLARSSL_RIPEMD160_ALT) + "POLARSSL_RIPEMD160_ALT", +#endif /* POLARSSL_RIPEMD160_ALT */ +#if defined(POLARSSL_SHA1_ALT) + "POLARSSL_SHA1_ALT", +#endif /* POLARSSL_SHA1_ALT */ +#if defined(POLARSSL_SHA256_ALT) + "POLARSSL_SHA256_ALT", +#endif /* POLARSSL_SHA256_ALT */ +#if defined(POLARSSL_SHA512_ALT) + "POLARSSL_SHA512_ALT", +#endif /* POLARSSL_SHA512_ALT */ +#if defined(POLARSSL_AES_ROM_TABLES) + "POLARSSL_AES_ROM_TABLES", +#endif /* POLARSSL_AES_ROM_TABLES */ +#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY) + "POLARSSL_CAMELLIA_SMALL_MEMORY", +#endif /* POLARSSL_CAMELLIA_SMALL_MEMORY */ +#if defined(POLARSSL_CIPHER_MODE_CBC) + "POLARSSL_CIPHER_MODE_CBC", +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CIPHER_MODE_CFB) + "POLARSSL_CIPHER_MODE_CFB", +#endif /* POLARSSL_CIPHER_MODE_CFB */ +#if defined(POLARSSL_CIPHER_MODE_CTR) + "POLARSSL_CIPHER_MODE_CTR", +#endif /* POLARSSL_CIPHER_MODE_CTR */ +#if defined(POLARSSL_CIPHER_NULL_CIPHER) + "POLARSSL_CIPHER_NULL_CIPHER", +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#if defined(POLARSSL_CIPHER_PADDING_PKCS7) + "POLARSSL_CIPHER_PADDING_PKCS7", +#endif /* POLARSSL_CIPHER_PADDING_PKCS7 */ +#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS) + "POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN) + "POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(POLARSSL_CIPHER_PADDING_ZEROS) + "POLARSSL_CIPHER_PADDING_ZEROS", +#endif /* POLARSSL_CIPHER_PADDING_ZEROS */ +#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) + "POLARSSL_ENABLE_WEAK_CIPHERSUITES", +#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */ +#if defined(POLARSSL_REMOVE_ARC4_CIPHERSUITES) + "POLARSSL_REMOVE_ARC4_CIPHERSUITES", +#endif /* POLARSSL_REMOVE_ARC4_CIPHERSUITES */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + "POLARSSL_ECP_DP_SECP192R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) + "POLARSSL_ECP_DP_SECP224R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) + "POLARSSL_ECP_DP_SECP256R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) + "POLARSSL_ECP_DP_SECP384R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) + "POLARSSL_ECP_DP_SECP521R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + "POLARSSL_ECP_DP_SECP192K1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + "POLARSSL_ECP_DP_SECP224K1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + "POLARSSL_ECP_DP_SECP256K1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) + "POLARSSL_ECP_DP_BP256R1_ENABLED", +#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) + "POLARSSL_ECP_DP_BP384R1_ENABLED", +#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) + "POLARSSL_ECP_DP_BP512R1_ENABLED", +#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_M221_ENABLED) + "POLARSSL_ECP_DP_M221_ENABLED", +#endif /* POLARSSL_ECP_DP_M221_ENABLED */ +#if defined(POLARSSL_ECP_DP_M255_ENABLED) + "POLARSSL_ECP_DP_M255_ENABLED", +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ +#if defined(POLARSSL_ECP_DP_M383_ENABLED) + "POLARSSL_ECP_DP_M383_ENABLED", +#endif /* POLARSSL_ECP_DP_M383_ENABLED */ +#if defined(POLARSSL_ECP_DP_M511_ENABLED) + "POLARSSL_ECP_DP_M511_ENABLED", +#endif /* POLARSSL_ECP_DP_M511_ENABLED */ +#if defined(POLARSSL_ECP_NIST_OPTIM) + "POLARSSL_ECP_NIST_OPTIM", +#endif /* POLARSSL_ECP_NIST_OPTIM */ +#if defined(POLARSSL_ECDSA_DETERMINISTIC) + "POLARSSL_ECDSA_DETERMINISTIC", +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(POLARSSL_PK_PARSE_EC_EXTENDED) + "POLARSSL_PK_PARSE_EC_EXTENDED", +#endif /* POLARSSL_PK_PARSE_EC_EXTENDED */ +#if defined(POLARSSL_ERROR_STRERROR_BC) + "POLARSSL_ERROR_STRERROR_BC", +#endif /* POLARSSL_ERROR_STRERROR_BC */ +#if defined(POLARSSL_ERROR_STRERROR_DUMMY) + "POLARSSL_ERROR_STRERROR_DUMMY", +#endif /* POLARSSL_ERROR_STRERROR_DUMMY */ +#if defined(POLARSSL_GENPRIME) + "POLARSSL_GENPRIME", +#endif /* POLARSSL_GENPRIME */ +#if defined(POLARSSL_FS_IO) + "POLARSSL_FS_IO", +#endif /* POLARSSL_FS_IO */ +#if defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) + "POLARSSL_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(POLARSSL_NO_PLATFORM_ENTROPY) + "POLARSSL_NO_PLATFORM_ENTROPY", +#endif /* POLARSSL_NO_PLATFORM_ENTROPY */ +#if defined(POLARSSL_ENTROPY_FORCE_SHA256) + "POLARSSL_ENTROPY_FORCE_SHA256", +#endif /* POLARSSL_ENTROPY_FORCE_SHA256 */ +#if defined(POLARSSL_MEMORY_DEBUG) + "POLARSSL_MEMORY_DEBUG", +#endif /* POLARSSL_MEMORY_DEBUG */ +#if defined(POLARSSL_MEMORY_BACKTRACE) + "POLARSSL_MEMORY_BACKTRACE", +#endif /* POLARSSL_MEMORY_BACKTRACE */ +#if defined(POLARSSL_PKCS1_V15) + "POLARSSL_PKCS1_V15", +#endif /* POLARSSL_PKCS1_V15 */ +#if defined(POLARSSL_PKCS1_V21) + "POLARSSL_PKCS1_V21", +#endif /* POLARSSL_PKCS1_V21 */ +#if defined(POLARSSL_RSA_NO_CRT) + "POLARSSL_RSA_NO_CRT", +#endif /* POLARSSL_RSA_NO_CRT */ +#if defined(POLARSSL_SELF_TEST) + "POLARSSL_SELF_TEST", +#endif /* POLARSSL_SELF_TEST */ +#if defined(POLARSSL_SSL_AEAD_RANDOM_IV) + "POLARSSL_SSL_AEAD_RANDOM_IV", +#endif /* POLARSSL_SSL_AEAD_RANDOM_IV */ +#if defined(POLARSSL_SSL_ALERT_MESSAGES) + "POLARSSL_SSL_ALERT_MESSAGES", +#endif /* POLARSSL_SSL_ALERT_MESSAGES */ +#if defined(POLARSSL_SSL_DEBUG_ALL) + "POLARSSL_SSL_DEBUG_ALL", +#endif /* POLARSSL_SSL_DEBUG_ALL */ +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + "POLARSSL_SSL_ENCRYPT_THEN_MAC", +#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + "POLARSSL_SSL_EXTENDED_MASTER_SECRET", +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ +#if defined(POLARSSL_SSL_FALLBACK_SCSV) + "POLARSSL_SSL_FALLBACK_SCSV", +#endif /* POLARSSL_SSL_FALLBACK_SCSV */ +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + "POLARSSL_SSL_HW_RECORD_ACCEL", +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) + "POLARSSL_SSL_CBC_RECORD_SPLITTING", +#endif /* POLARSSL_SSL_CBC_RECORD_SPLITTING */ +#if defined(POLARSSL_SSL_DISABLE_RENEGOTIATION) + "POLARSSL_SSL_DISABLE_RENEGOTIATION", +#endif /* POLARSSL_SSL_DISABLE_RENEGOTIATION */ +#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + "POLARSSL_SSL_MAX_FRAGMENT_LENGTH", +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(POLARSSL_SSL_PROTO_SSL3) + "POLARSSL_SSL_PROTO_SSL3", +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) + "POLARSSL_SSL_PROTO_TLS1", +#endif /* POLARSSL_SSL_PROTO_TLS1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_1) + "POLARSSL_SSL_PROTO_TLS1_1", +#endif /* POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + "POLARSSL_SSL_PROTO_TLS1_2", +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#if defined(POLARSSL_SSL_ALPN) + "POLARSSL_SSL_ALPN", +#endif /* POLARSSL_SSL_ALPN */ +#if defined(POLARSSL_SSL_SESSION_TICKETS) + "POLARSSL_SSL_SESSION_TICKETS", +#endif /* POLARSSL_SSL_SESSION_TICKETS */ +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + "POLARSSL_SSL_SERVER_NAME_INDICATION", +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + "POLARSSL_SSL_TRUNCATED_HMAC", +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_SET_CURVES) + "POLARSSL_SSL_SET_CURVES", +#endif /* POLARSSL_SSL_SET_CURVES */ +#if defined(POLARSSL_THREADING_ALT) + "POLARSSL_THREADING_ALT", +#endif /* POLARSSL_THREADING_ALT */ +#if defined(POLARSSL_THREADING_PTHREAD) + "POLARSSL_THREADING_PTHREAD", +#endif /* POLARSSL_THREADING_PTHREAD */ +#if defined(POLARSSL_VERSION_FEATURES) + "POLARSSL_VERSION_FEATURES", +#endif /* POLARSSL_VERSION_FEATURES */ +#if defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + "POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3", +#endif /* POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 */ +#if defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + "POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", +#endif /* POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + "POLARSSL_X509_CHECK_KEY_USAGE", +#endif /* POLARSSL_X509_CHECK_KEY_USAGE */ +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + "POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE", +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + "POLARSSL_X509_RSASSA_PSS_SUPPORT", +#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ +#if defined(POLARSSL_ZLIB_SUPPORT) + "POLARSSL_ZLIB_SUPPORT", +#endif /* POLARSSL_ZLIB_SUPPORT */ +#if defined(POLARSSL_AESNI_C) + "POLARSSL_AESNI_C", +#endif /* POLARSSL_AESNI_C */ +#if defined(POLARSSL_AES_C) + "POLARSSL_AES_C", +#endif /* POLARSSL_AES_C */ +#if defined(POLARSSL_ARC4_C) + "POLARSSL_ARC4_C", +#endif /* POLARSSL_ARC4_C */ +#if defined(POLARSSL_ASN1_PARSE_C) + "POLARSSL_ASN1_PARSE_C", +#endif /* POLARSSL_ASN1_PARSE_C */ +#if defined(POLARSSL_ASN1_WRITE_C) + "POLARSSL_ASN1_WRITE_C", +#endif /* POLARSSL_ASN1_WRITE_C */ +#if defined(POLARSSL_BASE64_C) + "POLARSSL_BASE64_C", +#endif /* POLARSSL_BASE64_C */ +#if defined(POLARSSL_BIGNUM_C) + "POLARSSL_BIGNUM_C", +#endif /* POLARSSL_BIGNUM_C */ +#if defined(POLARSSL_BLOWFISH_C) + "POLARSSL_BLOWFISH_C", +#endif /* POLARSSL_BLOWFISH_C */ +#if defined(POLARSSL_CAMELLIA_C) + "POLARSSL_CAMELLIA_C", +#endif /* POLARSSL_CAMELLIA_C */ +#if defined(POLARSSL_CCM_C) + "POLARSSL_CCM_C", +#endif /* POLARSSL_CCM_C */ +#if defined(POLARSSL_CERTS_C) + "POLARSSL_CERTS_C", +#endif /* POLARSSL_CERTS_C */ +#if defined(POLARSSL_CIPHER_C) + "POLARSSL_CIPHER_C", +#endif /* POLARSSL_CIPHER_C */ +#if defined(POLARSSL_CTR_DRBG_C) + "POLARSSL_CTR_DRBG_C", +#endif /* POLARSSL_CTR_DRBG_C */ +#if defined(POLARSSL_DEBUG_C) + "POLARSSL_DEBUG_C", +#endif /* POLARSSL_DEBUG_C */ +#if defined(POLARSSL_DES_C) + "POLARSSL_DES_C", +#endif /* POLARSSL_DES_C */ +#if defined(POLARSSL_DHM_C) + "POLARSSL_DHM_C", +#endif /* POLARSSL_DHM_C */ +#if defined(POLARSSL_ECDH_C) + "POLARSSL_ECDH_C", +#endif /* POLARSSL_ECDH_C */ +#if defined(POLARSSL_ECDSA_C) + "POLARSSL_ECDSA_C", +#endif /* POLARSSL_ECDSA_C */ +#if defined(POLARSSL_ECP_C) + "POLARSSL_ECP_C", +#endif /* POLARSSL_ECP_C */ +#if defined(POLARSSL_ENTROPY_C) + "POLARSSL_ENTROPY_C", +#endif /* POLARSSL_ENTROPY_C */ +#if defined(POLARSSL_ERROR_C) + "POLARSSL_ERROR_C", +#endif /* POLARSSL_ERROR_C */ +#if defined(POLARSSL_GCM_C) + "POLARSSL_GCM_C", +#endif /* POLARSSL_GCM_C */ +#if defined(POLARSSL_HAVEGE_C) + "POLARSSL_HAVEGE_C", +#endif /* POLARSSL_HAVEGE_C */ +#if defined(POLARSSL_HMAC_DRBG_C) + "POLARSSL_HMAC_DRBG_C", +#endif /* POLARSSL_HMAC_DRBG_C */ +#if defined(POLARSSL_MD_C) + "POLARSSL_MD_C", +#endif /* POLARSSL_MD_C */ +#if defined(POLARSSL_MD2_C) + "POLARSSL_MD2_C", +#endif /* POLARSSL_MD2_C */ +#if defined(POLARSSL_MD4_C) + "POLARSSL_MD4_C", +#endif /* POLARSSL_MD4_C */ +#if defined(POLARSSL_MD5_C) + "POLARSSL_MD5_C", +#endif /* POLARSSL_MD5_C */ +#if defined(POLARSSL_MEMORY_C) + "POLARSSL_MEMORY_C", +#endif /* POLARSSL_MEMORY_C */ +#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) + "POLARSSL_MEMORY_BUFFER_ALLOC_C", +#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */ +#if defined(POLARSSL_NET_C) + "POLARSSL_NET_C", +#endif /* POLARSSL_NET_C */ +#if defined(POLARSSL_OID_C) + "POLARSSL_OID_C", +#endif /* POLARSSL_OID_C */ +#if defined(POLARSSL_PADLOCK_C) + "POLARSSL_PADLOCK_C", +#endif /* POLARSSL_PADLOCK_C */ +#if defined(POLARSSL_PBKDF2_C) + "POLARSSL_PBKDF2_C", +#endif /* POLARSSL_PBKDF2_C */ +#if defined(POLARSSL_PEM_PARSE_C) + "POLARSSL_PEM_PARSE_C", +#endif /* POLARSSL_PEM_PARSE_C */ +#if defined(POLARSSL_PEM_WRITE_C) + "POLARSSL_PEM_WRITE_C", +#endif /* POLARSSL_PEM_WRITE_C */ +#if defined(POLARSSL_PK_C) + "POLARSSL_PK_C", +#endif /* POLARSSL_PK_C */ +#if defined(POLARSSL_PK_PARSE_C) + "POLARSSL_PK_PARSE_C", +#endif /* POLARSSL_PK_PARSE_C */ +#if defined(POLARSSL_PK_WRITE_C) + "POLARSSL_PK_WRITE_C", +#endif /* POLARSSL_PK_WRITE_C */ +#if defined(POLARSSL_PKCS5_C) + "POLARSSL_PKCS5_C", +#endif /* POLARSSL_PKCS5_C */ +#if defined(POLARSSL_PKCS11_C) + "POLARSSL_PKCS11_C", +#endif /* POLARSSL_PKCS11_C */ +#if defined(POLARSSL_PKCS12_C) + "POLARSSL_PKCS12_C", +#endif /* POLARSSL_PKCS12_C */ +#if defined(POLARSSL_PLATFORM_C) + "POLARSSL_PLATFORM_C", +#endif /* POLARSSL_PLATFORM_C */ +#if defined(POLARSSL_RIPEMD160_C) + "POLARSSL_RIPEMD160_C", +#endif /* POLARSSL_RIPEMD160_C */ +#if defined(POLARSSL_RSA_C) + "POLARSSL_RSA_C", +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_SHA1_C) + "POLARSSL_SHA1_C", +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) + "POLARSSL_SHA256_C", +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + "POLARSSL_SHA512_C", +#endif /* POLARSSL_SHA512_C */ +#if defined(POLARSSL_SSL_CACHE_C) + "POLARSSL_SSL_CACHE_C", +#endif /* POLARSSL_SSL_CACHE_C */ +#if defined(POLARSSL_SSL_CLI_C) + "POLARSSL_SSL_CLI_C", +#endif /* POLARSSL_SSL_CLI_C */ +#if defined(POLARSSL_SSL_SRV_C) + "POLARSSL_SSL_SRV_C", +#endif /* POLARSSL_SSL_SRV_C */ +#if defined(POLARSSL_SSL_TLS_C) + "POLARSSL_SSL_TLS_C", +#endif /* POLARSSL_SSL_TLS_C */ +#if defined(POLARSSL_THREADING_C) + "POLARSSL_THREADING_C", +#endif /* POLARSSL_THREADING_C */ +#if defined(POLARSSL_TIMING_C) + "POLARSSL_TIMING_C", +#endif /* POLARSSL_TIMING_C */ +#if defined(POLARSSL_VERSION_C) + "POLARSSL_VERSION_C", +#endif /* POLARSSL_VERSION_C */ +#if defined(POLARSSL_X509_USE_C) + "POLARSSL_X509_USE_C", +#endif /* POLARSSL_X509_USE_C */ +#if defined(POLARSSL_X509_CRT_PARSE_C) + "POLARSSL_X509_CRT_PARSE_C", +#endif /* POLARSSL_X509_CRT_PARSE_C */ +#if defined(POLARSSL_X509_CRL_PARSE_C) + "POLARSSL_X509_CRL_PARSE_C", +#endif /* POLARSSL_X509_CRL_PARSE_C */ +#if defined(POLARSSL_X509_CSR_PARSE_C) + "POLARSSL_X509_CSR_PARSE_C", +#endif /* POLARSSL_X509_CSR_PARSE_C */ +#if defined(POLARSSL_X509_CREATE_C) + "POLARSSL_X509_CREATE_C", +#endif /* POLARSSL_X509_CREATE_C */ +#if defined(POLARSSL_X509_CRT_WRITE_C) + "POLARSSL_X509_CRT_WRITE_C", +#endif /* POLARSSL_X509_CRT_WRITE_C */ +#if defined(POLARSSL_X509_CSR_WRITE_C) + "POLARSSL_X509_CSR_WRITE_C", +#endif /* POLARSSL_X509_CSR_WRITE_C */ +#if defined(POLARSSL_XTEA_C) + "POLARSSL_XTEA_C", +#endif /* POLARSSL_XTEA_C */ +#endif /* POLARSSL_VERSION_FEATURES */ + NULL +}; + +int version_check_feature( const char *feature ) +{ + const char **idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcasecmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* POLARSSL_VERSION_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/x509.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/x509.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,1088 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_USE_C) + +#include "polarssl/x509.h" +#include "polarssl/asn1.h" +#include "polarssl/oid.h" + +#include <stdio.h> +#include <string.h> + +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#include <stdlib.h> +#define polarssl_free free +#define polarssl_malloc malloc +#define polarssl_printf printf +#define polarssl_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include <windows.h> +#else +#include <time.h> +#endif + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#if !defined(_WIN32) +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#endif +#endif + +#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } + +/* + * CertificateSerialNumber ::= INTEGER + */ +int x509_get_serial( unsigned char **p, const unsigned char *end, + x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_SERIAL + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) && + **p != ASN1_INTEGER ) + return( POLARSSL_ERR_X509_INVALID_SERIAL + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( POLARSSL_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 x509_get_alg_null( unsigned char **p, const unsigned char *end, + x509_buf *alg ) +{ + int ret; + + if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) paramaters + */ +int x509_get_alg( unsigned char **p, const unsigned char *end, + x509_buf *alg, x509_buf *params ) +{ + int ret; + + if( ( ret = asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(POLARSSL_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 x509_buf *alg, md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_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 x509_get_rsassa_pss_params( const x509_buf *params, + md_type_t *md_alg, md_type_t *mgf_md, + int *salt_len ) +{ + int ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = POLARSSL_MD_SHA1; + *mgf_md = POLARSSL_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( ! OID_CMP( OID_MGF1, &alg_id ) ) + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE + + POLARSSL_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( POLARSSL_ERR_X509_INVALID_ALG ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* POLARSSL_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, + x509_name *cur ) +{ + int ret; + size_t len; + x509_buf *oid; + x509_buf *val; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_NAME + ret ); + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_NAME + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_NAME + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING && + **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING && + **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING && + **p != ASN1_BIT_STRING ) + return( POLARSSL_ERR_X509_INVALID_NAME + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 ) + return( POLARSSL_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 x509_dn_gets(). + */ +int x509_get_name( unsigned char **p, const unsigned char *end, + 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 = asn1_get_tag( p, end, &set_len, + ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) + return( POLARSSL_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 not the only one in a set */ + cur->next_merged = 1; + + cur->next = polarssl_malloc( sizeof( x509_name ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memset( cur->next, 0, sizeof( x509_name ) ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = polarssl_malloc( sizeof( x509_name ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memset( cur->next, 0, sizeof( x509_name ) ); + + 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 POLARSSL_ERR_X509_INVALID_DATE; + *res *= 10; + *res += (*(*p)++ - '0'); + } + return 0; +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int x509_get_time( unsigned char **p, const unsigned char *end, + x509_time *time ) +{ + int ret; + size_t len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == ASN1_UTC_TIME ) + { + (*p)++; + ret = asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( POLARSSL_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( POLARSSL_ERR_X509_INVALID_DATE ); + + time->year += 100 * ( time->year < 50 ); + time->year += 1900; + + return( 0 ); + } + else if( tag == ASN1_GENERALIZED_TIME ) + { + (*p)++; + ret = asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( POLARSSL_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( POLARSSL_ERR_X509_INVALID_DATE ); + + return( 0 ); + } + else + return( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); +} + +int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig ) +{ + int ret; + size_t len; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_SIGNATURE + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + sig->tag = **p; + + if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( POLARSSL_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 x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params, + md_type_t *md_alg, pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret; + + if( *sig_opts != NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == POLARSSL_PK_RSASSA_PSS ) + { + pk_rsassa_pss_options *pss_opts; + + pss_opts = polarssl_malloc( sizeof( pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + ret = x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + polarssl_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( POLARSSL_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 x509_get_ext( unsigned char **p, const unsigned char *end, + x509_buf *ext, int tag ) +{ + int ret; + size_t len; + + if( *p == end ) + return( 0 ); + + ext->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &ext->len, + ASN1_CONTEXT_SPECIFIC | 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 = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include <stdarg.h> + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int x509_dn_gets( char *buf, size_t size, const x509_name *dn ) +{ + int ret; + size_t i, n; + unsigned char c, merge = 0; + const x509_name *name; + const char *short_name = NULL; + char s[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 = polarssl_snprintf( p, n, merge ? " + " : ", " ); + SAFE_SNPRINTF(); + } + + ret = oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = polarssl_snprintf( p, n, "%s=", short_name ); + else + ret = polarssl_snprintf( p, n, "\?\?=" ); + 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 = polarssl_snprintf( p, n, "%s", s ); + 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 x509_serial_gets( char *buf, size_t size, const 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 = polarssl_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + SAFE_SNPRINTF(); + } + + if( nr != serial->len ) + { + ret = polarssl_snprintf( p, n, "...." ); + SAFE_SNPRINTF(); + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid, + pk_type_t pk_alg, md_type_t md_alg, + const void *sig_opts ) +{ + int ret; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = polarssl_snprintf( p, n, "???" ); + else + ret = polarssl_snprintf( p, n, "%s", desc ); + SAFE_SNPRINTF(); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == POLARSSL_PK_RSASSA_PSS ) + { + const pk_rsassa_pss_options *pss_opts; + const md_info_t *md_info, *mgf_md_info; + + pss_opts = (const pk_rsassa_pss_options *) sig_opts; + + md_info = md_info_from_type( md_alg ); + mgf_md_info = md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = polarssl_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? md_info->name : "???", + mgf_md_info ? mgf_md_info->name : "???", + pss_opts->expected_salt_len ); + SAFE_SNPRINTF(); + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int x509_key_size_helper( char *buf, size_t size, const char *name ) +{ + char *p = buf; + size_t n = size; + int ret; + + if( strlen( name ) + sizeof( " key size" ) > size ) + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); + + ret = polarssl_snprintf( p, n, "%s key size", name ); + SAFE_SNPRINTF(); + + return( 0 ); +} + +/* + * Return an informational string describing the given OID + */ +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +const char *x509_oid_get_description( x509_buf *oid ) +{ + const char *desc = NULL; + int ret; + + ret = oid_get_extended_key_usage( oid, &desc ); + + if( ret != 0 ) + return( NULL ); + + return( desc ); +} +#endif + +/* Return the x.y.z.... style numeric string for the given OID */ +#if ! defined(POLARSSL_DEPRECATED_REMOVED) +int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid ) +{ + return oid_get_numeric_string( buf, size, oid ); +} +#endif + +/* + * Return 0 if the x509_time is still valid, or 1 otherwise. + */ +#if defined(POLARSSL_HAVE_TIME) + +static void x509_get_current_time( x509_time *now ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + 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; +#else + struct tm lt; + time_t tt; + + tt = time( NULL ); + gmtime_r( &tt, < ); + + 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; +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const x509_time *before, const 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 x509_time_expired( const x509_time *to ) +{ + x509_time now; + + x509_get_current_time( &now ); + + return( x509_check_time( &now, to ) ); +} + +int x509_time_future( const x509_time *from ) +{ + x509_time now; + + x509_get_current_time( &now ); + + return( x509_check_time( from, &now ) ); +} + +#else /* POLARSSL_HAVE_TIME */ + +int x509_time_expired( const x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int x509_time_future( const x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* POLARSSL_HAVE_TIME */ + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/x509_crt.h" +#include "polarssl/certs.h" + +/* + * Checkup routine + */ +int x509_self_test( int verbose ) +{ +#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_SHA1_C) + int ret; + int flags; + x509_crt cacert; + x509_crt clicert; + + if( verbose != 0 ) + polarssl_printf( " X.509 certificate load: " ); + + x509_crt_init( &clicert ); + + ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt, + strlen( test_cli_crt ) ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( ret ); + } + + x509_crt_init( &cacert ); + + ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt, + strlen( test_ca_crt ) ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n X.509 signature verify: "); + + ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + polarssl_printf( "ret = %d, &flags = %04x\n", ret, flags ); + + return( ret ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n"); + + x509_crt_free( &cacert ); + x509_crt_free( &clicert ); + + return( 0 ); +#else + ((void) verbose); + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CERTS_C && POLARSSL_SHA1_C */ +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_X509_USE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/x509_create.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/x509_create.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,344 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CREATE_C) + +#include "polarssl/x509.h" +#include "polarssl/asn1write.h" +#include "polarssl/oid.h" + +#include <string.h> + +#if defined(_MSC_VER) && !defined strncasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strncasecmp _strnicmp +#endif + +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" ), OID_AT_CN }, + { ADD_STRLEN( "commonName" ), OID_AT_CN }, + { ADD_STRLEN( "C" ), OID_AT_COUNTRY }, + { ADD_STRLEN( "countryName" ), OID_AT_COUNTRY }, + { ADD_STRLEN( "O" ), OID_AT_ORGANIZATION }, + { ADD_STRLEN( "organizationName" ), OID_AT_ORGANIZATION }, + { ADD_STRLEN( "L" ), OID_AT_LOCALITY }, + { ADD_STRLEN( "locality" ), OID_AT_LOCALITY }, + { ADD_STRLEN( "R" ), OID_PKCS9_EMAIL }, + { ADD_STRLEN( "OU" ), OID_AT_ORG_UNIT }, + { ADD_STRLEN( "organizationalUnitName" ), OID_AT_ORG_UNIT }, + { ADD_STRLEN( "ST" ), OID_AT_STATE }, + { ADD_STRLEN( "stateOrProvinceName" ), OID_AT_STATE }, + { ADD_STRLEN( "emailAddress" ), OID_PKCS9_EMAIL }, + { ADD_STRLEN( "serialNumber" ), OID_AT_SERIAL_NUMBER }, + { ADD_STRLEN( "postalAddress" ), OID_AT_POSTAL_ADDRESS }, + { ADD_STRLEN( "postalCode" ), OID_AT_POSTAL_CODE }, + { ADD_STRLEN( "dnQualifier" ), OID_AT_DN_QUALIFIER }, + { ADD_STRLEN( "title" ), OID_AT_TITLE }, + { ADD_STRLEN( "surName" ), OID_AT_SUR_NAME }, + { ADD_STRLEN( "SN" ), OID_AT_SUR_NAME }, + { ADD_STRLEN( "givenName" ), OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "GN" ), OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "initials" ), OID_AT_INITIALS }, + { ADD_STRLEN( "pseudonym" ), OID_AT_PSEUDONYM }, + { ADD_STRLEN( "generationQualifier" ), OID_AT_GENERATION_QUALIFIER }, + { ADD_STRLEN( "domainComponent" ), OID_DOMAIN_COMPONENT }, + { ADD_STRLEN( "DC" ), 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 && + strncasecmp( cur->name, name, name_len ) == 0 ) + break; + + return( cur->oid ); +} + +int x509_string_to_names( 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[X509_MAX_DN_NAME_SIZE]; + char *d = data; + + /* Clear existing chain if present */ + 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 = POLARSSL_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 = POLARSSL_ERR_X509_INVALID_NAME; + goto exit; + } + } + else if( !in_tag && ( *c == ',' || c == end ) ) + { + if( asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ) == NULL ) + { + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + } + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + + if( !in_tag && s != c + 1 ) + { + *(d++) = *c; + + if( d - data == X509_MAX_DN_NAME_SIZE ) + { + ret = POLARSSL_ERR_X509_INVALID_NAME; + goto exit; + } + } + + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + asn1_named_data *cur; + + if( ( cur = asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( POLARSSL_ERR_X509_MALLOC_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 OID_PKCS9_EMAIL + // + if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len && + memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 ) + { + ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start, + (const char *) name, + name_len ) ); + } + else + { + ASN1_CHK_ADD( len, asn1_write_printable_string( p, start, + (const char *) name, + name_len ) ); + } + + // Write OID + // + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SET ) ); + + return( (int) len ); +} + +int x509_write_names( unsigned char **p, unsigned char *start, + asn1_named_data *first ) +{ + int ret; + size_t len = 0; + asn1_named_data *cur = first; + + while( cur != NULL ) + { + 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; + } + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int 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 < (int) size + 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + *--(*p) = 0; + len += 1; + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) ); + + // Write OID + // + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + asn1_named_data *ext ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) ); + } + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + 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 x509_write_extensions( unsigned char **p, unsigned char *start, + asn1_named_data *first ) +{ + int ret; + size_t len = 0; + asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* POLARSSL_X509_CREATE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/x509_crl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/x509_crl.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,768 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CRL_PARSE_C) + +#include "polarssl/x509_crl.h" +#include "polarssl/oid.h" + +#include <string.h> + +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#include <stdio.h> +#define polarssl_free free +#define polarssl_malloc malloc +#define polarssl_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include <windows.h> +#else +#include <time.h> +#endif + +#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32) +#include <stdio.h> +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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 = asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( POLARSSL_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, + x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* Get explicit tag */ + if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_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, + 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 = asn1_get_tag( p, end, &ext->len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + x509_crl_entry *entry ) +{ + int ret; + size_t entry_len; + x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = asn1_get_tag( p, end, &entry_len, + ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + if( ( ret = asn1_get_tag( p, end, &len2, + ASN1_SEQUENCE | 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 = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = 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 = polarssl_malloc( sizeof( x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memset( cur_entry->next, 0, sizeof( x509_crl_entry ) ); + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int x509_crl_parse_der( x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + x509_buf sig_params1, sig_params2; + x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( x509_buf ) ); + memset( &sig_params2, 0, sizeof( 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 = polarssl_malloc( sizeof( x509_crl ) ); + + if( crl->next == NULL ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + } + + x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( ( p = polarssl_malloc( buflen ) ) == NULL ) + return( POLARSSL_ERR_X509_MALLOC_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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_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 = x509_get_alg( &p, end, &crl->sig_oid1, &sig_params1 ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + crl->version++; + + if( crl->version > 2 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); + } + + if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_OUT_OF_DATA ) ) + { + 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 ) + { + 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 ) + { + x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, &sig_params2 ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid1.len != crl->sig_oid2.len || + memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(POLARSSL_PEM_PARSE_C) + int ret; + size_t use_len; + pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + do + { + pem_init( &pem ); + ret = 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 = x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + return( ret ); + } + + pem_free( &pem ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } + } + while( is_pem && buflen > 0 ); + + if( is_pem ) + return( 0 ); + else +#endif /* POLARSSL_PEM_PARSE_C */ + return( x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int x509_crl_parse_file( x509_crl *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509_crl_parse( chain, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include <stdarg.h> + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int x509_crl_info( char *buf, size_t size, const char *prefix, + const x509_crl *crl ) +{ + int ret; + size_t n; + char *p; + const x509_crl_entry *entry; + + p = buf; + n = size; + + ret = polarssl_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + SAFE_SNPRINTF(); + + ret = polarssl_snprintf( p, n, "\n%sissuer name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &crl->issuer ); + SAFE_SNPRINTF(); + + ret = polarssl_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 ); + SAFE_SNPRINTF(); + + ret = polarssl_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 ); + SAFE_SNPRINTF(); + + entry = &crl->entry; + + ret = polarssl_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + SAFE_SNPRINTF(); + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = polarssl_snprintf( p, n, "\n%sserial number: ", + prefix ); + SAFE_SNPRINTF(); + + ret = x509_serial_gets( p, n, &entry->serial ); + SAFE_SNPRINTF(); + + ret = polarssl_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 ); + SAFE_SNPRINTF(); + + entry = entry->next; + } + + ret = polarssl_snprintf( p, n, "\n%ssigned using : ", prefix ); + SAFE_SNPRINTF(); + + ret = x509_sig_alg_gets( p, n, &crl->sig_oid1, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + SAFE_SNPRINTF(); + + ret = polarssl_snprintf( p, n, "\n" ); + SAFE_SNPRINTF(); + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void x509_crl_init( x509_crl *crl ) +{ + memset( crl, 0, sizeof(x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void x509_crl_free( x509_crl *crl ) +{ + x509_crl *crl_cur = crl; + x509_crl *crl_prv; + x509_name *name_cur; + x509_name *name_prv; + x509_crl_entry *entry_cur; + x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + polarssl_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; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + polarssl_zeroize( entry_prv, sizeof( x509_crl_entry ) ); + polarssl_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + polarssl_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + polarssl_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; + + polarssl_zeroize( crl_prv, sizeof( x509_crl ) ); + if( crl_prv != crl ) + polarssl_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* POLARSSL_X509_CRL_PARSE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/x509_crt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/x509_crt.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,2158 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + +#include "polarssl/x509_crt.h" +#include "polarssl/oid.h" + +#include <stdio.h> +#include <string.h> + +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#define polarssl_free free +#define polarssl_malloc malloc +#define polarssl_snprintf snprintf +#endif + +#if defined(POLARSSL_THREADING_C) +#include "polarssl/threading.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include <windows.h> +#else +#include <time.h> +#endif + +#if defined(POLARSSL_FS_IO) +#include <stdio.h> +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( ret ); + } + + end = *p + len; + + if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_VERSION + ret ); + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_VERSION + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + x509_time *from, + x509_time *to ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_DATE + ret ); + + end = *p + len; + + if( ( ret = x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_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, + x509_buf *uid, int n ) +{ + int ret; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &uid->len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == POLARSSL_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 = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p == end ) + return( 0 ); + + if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + ret = asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_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; + x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len != 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_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 char *key_usage) +{ + int ret; + x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len < 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *key_usage = *bs.p; + 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, + x509_sequence *ext_key_usage) +{ + int ret; + + if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_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, + x509_sequence *subject_alt_name ) +{ + int ret; + size_t len, tag_len; + asn1_buf *buf; + unsigned char tag; + asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + (*p)++; + if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + /* Skip everything but DNS name */ + if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) ) + { + *p += tag_len; + continue; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = polarssl_malloc( sizeof( asn1_sequence ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_MALLOC_FAILED ); + + memset( cur->next, 0, sizeof( asn1_sequence ) ); + 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( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_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, + x509_crt *crt ) +{ + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + extn_oid.tag = **p; + + if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.p = *p; + *p += extn_oid.len; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + /* Get optional critical */ + if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = asn1_get_tag( p, end_ext_data, &len, + ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case 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 EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case 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 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 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( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + } + } + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf, + size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end, *crt_end; + x509_buf sig_params1, sig_params2; + + memset( &sig_params1, 0, sizeof( x509_buf ) ); + memset( &sig_params2, 0, sizeof( x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + p = polarssl_malloc( len = buflen ); + + if( p == NULL ) + return( POLARSSL_ERR_X509_MALLOC_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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT ); + } + + if( len > (size_t) ( end - p ) ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_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 = x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = x509_get_alg( &p, end, &crt->sig_oid1, + &sig_params1 ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + crt->version++; + + if( crt->version > 3 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); + } + + if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + 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 ) + { + x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + if( ( ret = pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + 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 ) + { + 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 ) + { + x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) + { +#endif + ret = x509_get_crt_ext( &p, end, crt ); + if( ret != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } +#if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + } +#endif + + if( p != end ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2, &sig_params2 ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid1.len != crt->sig_oid2.len || + memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_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 x509_crt_parse_der( x509_crt *chain, const unsigned char *buf, + size_t buflen ) +{ + int ret; + x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( POLARSSL_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 = polarssl_malloc( sizeof( x509_crt ) ); + + if( crt->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + prev = crt; + 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 ) + polarssl_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen ) +{ + int success = 0, first_error = 0, total_failed = 0; + int buf_format = X509_FORMAT_DER; + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(POLARSSL_PEM_PARSE_C) + if( strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + buf_format = X509_FORMAT_PEM; +#endif + + if( buf_format == X509_FORMAT_DER ) + return x509_crt_parse_der( chain, buf, buflen ); + +#if defined(POLARSSL_PEM_PARSE_C) + if( buf_format == X509_FORMAT_PEM ) + { + int ret; + pem_context pem; + + while( buflen > 0 ) + { + size_t use_len; + pem_init( &pem ); + + ret = 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 == POLARSSL_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + 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 = x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == POLARSSL_ERR_X509_MALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } +#endif /* POLARSSL_PEM_PARSE_C */ + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int x509_crt_parse_file( x509_crt *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509_crt_parse( chain, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} + +#if defined(POLARSSL_THREADING_PTHREAD) +static threading_mutex_t readdir_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +int x509_crt_parse_path( 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; + int len = (int) strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( POLARSSL_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( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( POLARSSL_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, len - 1, + NULL, NULL ); + if( w_ret == 0 ) + return( POLARSSL_ERR_X509_FILE_IO_ERROR ); + + w_ret = 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 = POLARSSL_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( POLARSSL_ERR_X509_FILE_IO_ERROR ); + +#if defined(POLARSSL_THREADING_PTHREAD) + if( ( ret = polarssl_mutex_lock( &readdir_mutex ) ) != 0 ) + return( ret ); +#endif + + while( ( entry = readdir( dir ) ) != NULL ) + { + polarssl_snprintf( entry_name, sizeof entry_name, "%s/%s", path, entry->d_name ); + + if( stat( entry_name, &sb ) == -1 ) + { + closedir( dir ); + ret = POLARSSL_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + closedir( dir ); + +cleanup: +#if defined(POLARSSL_THREADING_PTHREAD) + if( polarssl_mutex_unlock( &readdir_mutex ) != 0 ) + ret = POLARSSL_ERR_THREADING_MUTEX_ERROR; +#endif + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include <stdarg.h> + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const x509_sequence *subject_alt_name ) +{ + size_t i; + size_t n = *size; + char *p = *buf; + const 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( POLARSSL_ERR_DEBUG_BUF_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 = polarssl_snprintf( p, n, "%s" i, sep ); \ + 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( NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( 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 char key_usage ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( KU_CRL_SIGN, "CRL Sign" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const x509_sequence *extended_key_usage ) +{ + int ret; + const char *desc; + size_t n = *size; + char *p = *buf; + const x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = polarssl_snprintf( p, n, "%s%s", sep, desc ); + 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 x509_crt_info( char *buf, size_t size, const char *prefix, + const x509_crt *crt ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = polarssl_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + SAFE_SNPRINTF(); + ret = polarssl_snprintf( p, n, "%sserial number : ", + prefix ); + SAFE_SNPRINTF(); + + ret = x509_serial_gets( p, n, &crt->serial ); + SAFE_SNPRINTF(); + + ret = polarssl_snprintf( p, n, "\n%sissuer name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &crt->issuer ); + SAFE_SNPRINTF(); + + ret = polarssl_snprintf( p, n, "\n%ssubject name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &crt->subject ); + SAFE_SNPRINTF(); + + ret = polarssl_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 ); + SAFE_SNPRINTF(); + + ret = polarssl_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 ); + SAFE_SNPRINTF(); + + ret = polarssl_snprintf( p, n, "\n%ssigned using : ", prefix ); + SAFE_SNPRINTF(); + + ret = x509_sig_alg_gets( p, n, &crt->sig_oid1, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + SAFE_SNPRINTF(); + + /* Key size */ + if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON, + pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = polarssl_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) pk_get_size( &crt->pk ) ); + SAFE_SNPRINTF(); + + /* + * Optional extensions + */ + + if( crt->ext_types & EXT_BASIC_CONSTRAINTS ) + { + ret = polarssl_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + SAFE_SNPRINTF(); + + if( crt->max_pathlen > 0 ) + { + ret = polarssl_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + SAFE_SNPRINTF(); + } + } + + if( crt->ext_types & EXT_SUBJECT_ALT_NAME ) + { + ret = polarssl_snprintf( p, n, "\n%ssubject alt name : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & EXT_NS_CERT_TYPE ) + { + ret = polarssl_snprintf( p, n, "\n%scert. type : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & EXT_KEY_USAGE ) + { + ret = polarssl_snprintf( p, n, "\n%skey usage : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & EXT_EXTENDED_KEY_USAGE ) + { + ret = polarssl_snprintf( p, n, "\n%sext key usage : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + ret = polarssl_snprintf( p, n, "\n" ); + 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[] = { + { BADCERT_EXPIRED, "The certificate validity has expired" }, + { BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { BADCRL_EXPIRED, "The CRL is expired" }, + { BADCERT_MISSING, "Certificate was missing" }, + { BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { BADCERT_FUTURE, "The certificate validity starts in the future" }, + { BADCRL_FUTURE, "The CRL is from the future" }, + { BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { 0, NULL } +}; + +int x509_crt_verify_info( char *buf, size_t size, const char *prefix, + int 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 = polarssl_snprintf( p, n, "%s%s\n", prefix, cur->string ); + SAFE_SNPRINTF(); + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = polarssl_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + SAFE_SNPRINTF(); + } + + return( (int) ( size - n ) ); +} + +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) +int x509_crt_check_key_usage( const x509_crt *crt, int usage ) +{ + if( ( crt->ext_types & EXT_KEY_USAGE ) != 0 && + ( crt->key_usage & usage ) != usage ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) +int x509_crt_check_extended_key_usage( const x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & 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 x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( OID_CMP( OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) ) + return( 0 ); + } + + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(POLARSSL_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl ) +{ + const 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( x509_time_expired( &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( x509_crt *crt, x509_crt *ca, + x509_crl *crl_list) +{ + int flags = 0; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + const 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(POLARSSL_X509_CHECK_KEY_USAGE) + if( x509_crt_check_key_usage( ca, KU_CRL_SIGN ) != 0 ) + { + flags |= BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + md_info = md_info_from_type( crl_list->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + flags |= BADCRL_NOT_TRUSTED; + break; + } + + md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); + + if( pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, md_info->size, + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( x509_time_expired( &crl_list->next_update ) ) + flags |= BADCRL_EXPIRED; + + if( x509_time_future( &crl_list->this_update ) ) + flags |= BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( x509_crt_revoked( crt, crl_list ) ) + { + flags |= BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + return( flags ); +} +#endif /* POLARSSL_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 1 if match, 0 if not + * TODO: inverted return value! + */ +static int x509_wildcard_verify( const char *cn, 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( 0 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 1 ); + } + + return( 0 ); +} + +/* + * 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 x509_buf *a, const 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 == ASN1_UTF8_STRING || a->tag == ASN1_PRINTABLE_STRING ) && + ( b->tag == ASN1_UTF8_STRING || b->tag == 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 x509_name *a, const 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 x509_crt *child, + const 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(POLARSSL_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +static int x509_crt_verify_top( + x509_crt *child, x509_crt *trust_ca, + x509_crl *ca_crl, int path_cnt, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + int ret; + int ca_flags = 0, check_path_cnt; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + const md_info_t *md_info; + + if( x509_time_expired( &child->valid_to ) ) + *flags |= BADCERT_EXPIRED; + + if( x509_time_future( &child->valid_from ) ) + *flags |= BADCERT_FUTURE; + + /* + * Child is the top of the chain. Check against the trust_ca list. + */ + *flags |= BADCERT_NOT_TRUSTED; + + md_info = md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown', no need to try any CA + */ + trust_ca = NULL; + } + else + 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--; + } + + if( trust_ca->max_pathlen > 0 && + trust_ca->max_pathlen < check_path_cnt ) + { + continue; + } + + if( pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, + child->sig_md, hash, md_info->size, + child->sig.p, child->sig.len ) != 0 ) + { + continue; + } + + /* + * Top of chain is signed by a trusted CA + */ + *flags &= ~BADCERT_NOT_TRUSTED; + 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(POLARSSL_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the chain's top crt */ + *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl ); +#else + ((void) ca_crl); +#endif + + if( x509_time_expired( &trust_ca->valid_to ) ) + ca_flags |= BADCERT_EXPIRED; + + if( x509_time_future( &trust_ca->valid_from ) ) + ca_flags |= 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( + x509_crt *child, x509_crt *parent, x509_crt *trust_ca, + x509_crl *ca_crl, int path_cnt, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + int ret; + int parent_flags = 0; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + x509_crt *grandparent; + const md_info_t *md_info; + + /* path_cnt is 0 for the first intermediate CA */ + if( 1 + path_cnt > POLARSSL_X509_MAX_INTERMEDIATE_CA ) + { + *flags |= BADCERT_NOT_TRUSTED; + return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); + } + + if( x509_time_expired( &child->valid_to ) ) + *flags |= BADCERT_EXPIRED; + + if( x509_time_future( &child->valid_from ) ) + *flags |= BADCERT_FUTURE; + + md_info = md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + *flags |= BADCERT_NOT_TRUSTED; + } + else + { + md( md_info, child->tbs.p, child->tbs.len, hash ); + + if( pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, md_info->size, + child->sig.p, child->sig.len ) != 0 ) + { + *flags |= BADCERT_NOT_TRUSTED; + } + } + +#if defined(POLARSSL_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl(child, parent, ca_crl); +#endif + + /* Look for a grandparent upwards the chain */ + for( grandparent = parent->next; + grandparent != NULL; + grandparent = grandparent->next ) + { + 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, + path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( parent, trust_ca, ca_crl, + path_cnt + 1, &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 x509_crt_verify( x509_crt *crt, + x509_crt *trust_ca, + x509_crl *ca_crl, + const char *cn, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + size_t cn_len; + int ret; + int pathlen = 0; + x509_crt *parent; + x509_name *name; + x509_sequence *cur = NULL; + + *flags = 0; + + if( cn != NULL ) + { + name = &crt->subject; + cn_len = strlen( cn ); + + if( crt->ext_types & 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_wildcard_verify( cn, &cur->buf ) ) + break; + + cur = cur->next; + } + + if( cur == NULL ) + *flags |= BADCERT_CN_MISMATCH; + } + else + { + while( name != NULL ) + { + if( OID_CMP( OID_AT_CN, &name->oid ) ) + { + 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_wildcard_verify( cn, &name->val ) ) + break; + } + + name = name->next; + } + + if( name == NULL ) + *flags |= BADCERT_CN_MISMATCH; + } + } + + /* 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, + pathlen, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( crt, trust_ca, ca_crl, + pathlen, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + + if( *flags != 0 ) + return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + +/* + * Initialize a certificate chain + */ +void x509_crt_init( x509_crt *crt ) +{ + memset( crt, 0, sizeof(x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void x509_crt_free( x509_crt *crt ) +{ + x509_crt *cert_cur = crt; + x509_crt *cert_prv; + x509_name *name_cur; + x509_name *name_prv; + x509_sequence *seq_cur; + x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + pk_free( &cert_cur->pk ); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + polarssl_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; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + polarssl_zeroize( seq_prv, sizeof( x509_sequence ) ); + polarssl_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + polarssl_zeroize( seq_prv, sizeof( x509_sequence ) ); + polarssl_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL ) + { + polarssl_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + polarssl_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; + + polarssl_zeroize( cert_prv, sizeof( x509_crt ) ); + if( cert_prv != crt ) + polarssl_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#endif /* POLARSSL_X509_CRT_PARSE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/x509_csr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/x509_csr.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,466 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CSR_PARSE_C) + +#include "polarssl/x509_csr.h" +#include "polarssl/oid.h" + +#include <string.h> + +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdlib.h> +#include <stdio.h> +#define polarssl_free free +#define polarssl_malloc malloc +#define polarssl_snprintf snprintf +#endif + +#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32) +#include <stdio.h> +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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 = asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( POLARSSL_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int x509_csr_parse_der( x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + x509_buf sig_params; + + memset( &sig_params, 0, sizeof( x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = polarssl_malloc( len = buflen ); + + if( p == NULL ) + return( POLARSSL_ERR_X509_MALLOC_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 = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_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 ) + { + x509_csr_free( csr ); + return( ret ); + } + + csr->version++; + + if( csr->version != 1 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); + } + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_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 = x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ + int ret; +#if defined(POLARSSL_PEM_PARSE_C) + size_t use_len; + pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + +#if defined(POLARSSL_PEM_PARSE_C) + pem_init( &pem ); + ret = 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 = x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) + return( ret ); + + pem_free( &pem ); + return( 0 ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } + else +#endif /* POLARSSL_PEM_PARSE_C */ + return( x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load a CSR into the structure + */ +int x509_csr_parse_file( x509_csr *csr, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509_csr_parse( csr, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include <stdarg.h> + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int x509_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = polarssl_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + SAFE_SNPRINTF(); + + ret = polarssl_snprintf( p, n, "\n%ssubject name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &csr->subject ); + SAFE_SNPRINTF(); + + ret = polarssl_snprintf( p, n, "\n%ssigned using : ", prefix ); + SAFE_SNPRINTF(); + + ret = x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + SAFE_SNPRINTF(); + + if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON, + pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = polarssl_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) pk_get_size( &csr->pk ) ); + SAFE_SNPRINTF(); + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void x509_csr_init( x509_csr *csr ) +{ + memset( csr, 0, sizeof(x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void x509_csr_free( x509_csr *csr ) +{ + x509_name *name_cur; + x509_name *name_prv; + + if( csr == NULL ) + return; + + pk_free( &csr->pk ); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + polarssl_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + polarssl_zeroize( csr->raw.p, csr->raw.len ); + polarssl_free( csr->raw.p ); + } + + polarssl_zeroize( csr, sizeof( x509_csr ) ); +} + +#endif /* POLARSSL_X509_CSR_PARSE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/x509write_crt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/x509write_crt.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,452 @@ +/* + * X.509 certificate writing + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * 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(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CRT_WRITE_C) + +#include "polarssl/x509_crt.h" +#include "polarssl/oid.h" +#include "polarssl/asn1write.h" +#include "polarssl/sha1.h" + +#include <string.h> + +#if defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif /* POLARSSL_PEM_WRITE_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void x509write_crt_init( x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof(x509write_cert) ); + + mpi_init( &ctx->serial ); + ctx->version = X509_CRT_VERSION_3; +} + +void x509write_crt_free( x509write_cert *ctx ) +{ + mpi_free( &ctx->serial ); + + asn1_free_named_data_list( &ctx->subject ); + asn1_free_named_data_list( &ctx->issuer ); + asn1_free_named_data_list( &ctx->extensions ); + + polarssl_zeroize( ctx, sizeof(x509write_cert) ); +} + +void x509write_crt_set_version( x509write_cert *ctx, int version ) +{ + ctx->version = version; +} + +void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key ) +{ + ctx->subject_key = key; +} + +void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key ) +{ + ctx->issuer_key = key; +} + +int x509write_crt_set_subject_name( x509write_cert *ctx, + const char *subject_name ) +{ + return x509_string_to_names( &ctx->subject, subject_name ); +} + +int x509write_crt_set_issuer_name( x509write_cert *ctx, + const char *issuer_name ) +{ + return x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial ) +{ + int ret; + + if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int x509write_crt_set_extension( x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ); +} + +int x509write_crt_set_basic_constraints( 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( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) ); + } + ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) ); + } + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS, + OID_SIZE( OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ); +} + +#if defined(POLARSSL_SHA1_C) +int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) ); + + return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER, + OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER, + OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} +#endif /* POLARSSL_SHA1_C */ + +int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + return( ret ); + + ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ), + 1, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_crt_set_ns_cert_type( x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE, + OID_SIZE( 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 ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) + { + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) time + 2, + size - 2 ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) ); + } + else + { + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) time, + size ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int x509write_crt_der( 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[POLARSSL_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; + 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 = pk_get_type( ctx->issuer_key ); + if( pk_alg == POLARSSL_PK_ECKEY ) + pk_alg = POLARSSL_PK_ECDSA; + + if( ( ret = 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 + */ + ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | + ASN1_CONSTRUCTED | 3 ) ); + + /* + * SubjectPublicKeyInfo + */ + ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, + X509_RFC5280_UTC_TIME_LEN ) ); + + ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, + X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + sub_len = 0; + ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) ); + len += sub_len; + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | + ASN1_CONSTRUCTED | 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + md( md_info_from_type( ctx->md_alg ), c, len, hash ); + + if( ( ret = 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; + ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(POLARSSL_PEM_WRITE_C) +int x509write_crt_pem( 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 = x509write_crt_der( crt, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = 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 /* POLARSSL_PEM_WRITE_C */ + +#endif /* POLARSSL_X509_CRT_WRITE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/x509write_csr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/x509write_csr.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,258 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CSR_WRITE_C) + +#include "polarssl/x509_csr.h" +#include "polarssl/oid.h" +#include "polarssl/asn1write.h" + +#include <string.h> +#include <stdlib.h> + +#if defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void x509write_csr_init( x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof(x509write_csr) ); +} + +void x509write_csr_free( x509write_csr *ctx ) +{ + asn1_free_named_data_list( &ctx->subject ); + asn1_free_named_data_list( &ctx->extensions ); + + polarssl_zeroize( ctx, sizeof(x509write_csr) ); +} + +void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void x509write_csr_set_key( x509write_csr *ctx, pk_context *key ) +{ + ctx->key = key; +} + +int x509write_csr_set_subject_name( x509write_csr *ctx, + const char *subject_name ) +{ + return x509_string_to_names( &ctx->subject, subject_name ); +} + +int x509write_csr_set_extension( x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + +int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_csr_set_ns_cert_type( x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE, + OID_SIZE( OID_NS_CERT_TYPE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_csr_der( 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[POLARSSL_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + + if( len ) + { + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SET ) ); + + ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ, + OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + } + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_CONTEXT_SPECIFIC ) ); + + ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + /* + * Prepare signature + */ + md( md_info_from_type( ctx->md_alg ), c, len, hash ); + + pk_alg = pk_get_type( ctx->key ); + if( pk_alg == POLARSSL_PK_ECKEY ) + pk_alg = POLARSSL_PK_ECDSA; + + if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 || + ( ret = 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; + ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(POLARSSL_PEM_WRITE_C) +int x509write_csr_pem( 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 = x509write_csr_der( ctx, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = 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 /* POLARSSL_PEM_WRITE_C */ + +#endif /* POLARSSL_X509_CSR_WRITE_C */ +
diff -r 000000000000 -r 137634ff4186 polarssl/xtea.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/polarssl/xtea.c Thu Jun 11 03:27:03 2015 +0000 @@ -0,0 +1,283 @@ +/* + * An 32-bit implementation of the XTEA algorithm + * + * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_XTEA_C) + +#include "polarssl/xtea.h" + +#include <string.h> + +#if defined(POLARSSL_SELF_TEST) +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include <stdio.h> +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_C */ +#endif /* POLARSSL_SELF_TEST */ + +#if !defined(POLARSSL_XTEA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_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 xtea_init( xtea_context *ctx ) +{ + memset( ctx, 0, sizeof( xtea_context ) ); +} + +void xtea_free( xtea_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( xtea_context ) ); +} + +/* + * XTEA key schedule + */ +void xtea_setup( xtea_context *ctx, const unsigned char key[16] ) +{ + int i; + + memset( ctx, 0, sizeof(xtea_context) ); + + for( i = 0; i < 4; i++ ) + { + GET_UINT32_BE( ctx->k[i], key, i << 2 ); + } +} + +/* + * XTEA encrypt function + */ +int xtea_crypt_ecb( 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 == 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 /* 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(POLARSSL_CIPHER_MODE_CBC) +/* + * XTEA-CBC buffer encryption/decryption + */ +int xtea_crypt_cbc( 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( POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH ); + + if( mode == XTEA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + 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] ); + + xtea_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* !POLARSSL_XTEA_ALT */ + +#if defined(POLARSSL_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 xtea_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char buf[8]; + xtea_context ctx; + + xtea_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " XTEA test #%d: ", i + 1 ); + + memcpy( buf, xtea_test_pt[i], 8 ); + + xtea_setup( &ctx, xtea_test_key[i] ); + xtea_crypt_ecb( &ctx, XTEA_ENCRYPT, buf, buf ); + + if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + xtea_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_XTEA_C */ +